Blog
This commit is contained in:
64
package-lock.json
generated
64
package-lock.json
generated
@@ -23,6 +23,7 @@
|
|||||||
"eslint": "^9.0.0",
|
"eslint": "^9.0.0",
|
||||||
"eslint-plugin-svelte": "^2.36.0",
|
"eslint-plugin-svelte": "^2.36.0",
|
||||||
"globals": "^15.0.0",
|
"globals": "^15.0.0",
|
||||||
|
"mdsvex": "^0.12.3",
|
||||||
"postcss": "^8.4.47",
|
"postcss": "^8.4.47",
|
||||||
"postcss-nested": "^6.2.0",
|
"postcss-nested": "^6.2.0",
|
||||||
"svelte": "^4.2.7",
|
"svelte": "^4.2.7",
|
||||||
@@ -1583,6 +1584,12 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
|
||||||
"integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q=="
|
"integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q=="
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/unist": {
|
||||||
|
"version": "2.0.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
|
||||||
|
"integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||||
"version": "8.7.0",
|
"version": "8.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.7.0.tgz",
|
||||||
@@ -3196,6 +3203,21 @@
|
|||||||
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
|
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
|
||||||
"integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA=="
|
"integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/mdsvex": {
|
||||||
|
"version": "0.12.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/mdsvex/-/mdsvex-0.12.3.tgz",
|
||||||
|
"integrity": "sha512-C/uIJamjNo5PHHnR3JHqsBPoLcfUBpzRmAEB6FLMXI/s7XHOceswjDMKqSPEW2WHmYpKm0taZ3U20GSyhMridA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/unist": "^2.0.3",
|
||||||
|
"prism-svelte": "^0.4.7",
|
||||||
|
"prismjs": "^1.17.1",
|
||||||
|
"vfile-message": "^2.0.4"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"svelte": "^3.56.0 || ^4.0.0 || ^5.0.0-next.120"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/merge2": {
|
"node_modules/merge2": {
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
|
||||||
@@ -3720,6 +3742,21 @@
|
|||||||
"node": ">= 0.8.0"
|
"node": ">= 0.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/prism-svelte": {
|
||||||
|
"version": "0.4.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/prism-svelte/-/prism-svelte-0.4.7.tgz",
|
||||||
|
"integrity": "sha512-yABh19CYbM24V7aS7TuPYRNMqthxwbvx6FF/Rw920YbyBWO3tnyPIqRMgHuSVsLmuHkkBS1Akyof463FVdkeDQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/prismjs": {
|
||||||
|
"version": "1.29.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz",
|
||||||
|
"integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/punycode": {
|
"node_modules/punycode": {
|
||||||
"version": "2.3.1",
|
"version": "2.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||||
@@ -4547,6 +4584,19 @@
|
|||||||
"integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==",
|
"integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/unist-util-stringify-position": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-2.0.3.tgz",
|
||||||
|
"integrity": "sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/unist": "^2.0.2"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/unplugin": {
|
"node_modules/unplugin": {
|
||||||
"version": "1.14.1",
|
"version": "1.14.1",
|
||||||
"resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.14.1.tgz",
|
"resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.14.1.tgz",
|
||||||
@@ -4655,6 +4705,20 @@
|
|||||||
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/vfile-message": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-DjssxRGkMvifUOJre00juHoP9DPWuzjxKuMDrhNbk2TdaYYBNMStsNhEOt3idrtI12VQYM/1+iM0KOzXi4pxwQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@types/unist": "^2.0.0",
|
||||||
|
"unist-util-stringify-position": "^2.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/unified"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "5.4.7",
|
"version": "5.4.7",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.7.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-5.4.7.tgz",
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
"eslint": "^9.0.0",
|
"eslint": "^9.0.0",
|
||||||
"eslint-plugin-svelte": "^2.36.0",
|
"eslint-plugin-svelte": "^2.36.0",
|
||||||
"globals": "^15.0.0",
|
"globals": "^15.0.0",
|
||||||
|
"mdsvex": "^0.12.3",
|
||||||
"postcss": "^8.4.47",
|
"postcss": "^8.4.47",
|
||||||
"postcss-nested": "^6.2.0",
|
"postcss-nested": "^6.2.0",
|
||||||
"svelte": "^4.2.7",
|
"svelte": "^4.2.7",
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import "../app.css";
|
import "../app.css";
|
||||||
|
import Footer from "./Footer.svelte"
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
@@ -9,6 +10,8 @@
|
|||||||
|
|
||||||
<slot />
|
<slot />
|
||||||
|
|
||||||
|
<Footer></Footer>
|
||||||
|
|
||||||
<style lang="postcss">
|
<style lang="postcss">
|
||||||
:global(html) {
|
:global(html) {
|
||||||
background: theme(colors.slate.950);
|
background: theme(colors.slate.950);
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
import Hero from "./Hero.svelte";
|
import Hero from "./Hero.svelte";
|
||||||
import About from "./About.svelte";
|
import About from "./About.svelte";
|
||||||
import Projects from "./Projects/Projects.svelte";
|
import Projects from "./Projects/Projects.svelte";
|
||||||
import Footer from "./Footer.svelte";
|
|
||||||
import ContactForm from "./ContactForm/ContactForm.svelte";
|
import ContactForm from "./ContactForm/ContactForm.svelte";
|
||||||
|
|
||||||
export let data;
|
export let data;
|
||||||
@@ -15,5 +14,4 @@
|
|||||||
<About></About>
|
<About></About>
|
||||||
<Projects></Projects>
|
<Projects></Projects>
|
||||||
<ContactForm></ContactForm>
|
<ContactForm></ContactForm>
|
||||||
<Footer></Footer>
|
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
40
src/routes/blog/+layout.svelte
Normal file
40
src/routes/blog/+layout.svelte
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<article class="px-2 py-8 md:px-8 max-w-[980px] mx-auto text-lg">
|
||||||
|
<slot />
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<style lang="postcss">
|
||||||
|
:global(h1) {
|
||||||
|
@apply text-3xl my-6;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(h2) {
|
||||||
|
@apply text-3xl my-4;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(h3) {
|
||||||
|
@apply text-2xl my-2;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(h4) {
|
||||||
|
@apply text-xl my-2;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(pre, code) {
|
||||||
|
@apply rounded-lg border border-slate-500 bg-slate-900;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(pre) {
|
||||||
|
@apply p-6 my-6 overflow-auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(pre code) {
|
||||||
|
@apply p-0 border-none;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(code) {
|
||||||
|
@apply px-2 py-0.5;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
279
src/routes/blog/html-in-css/+page.svx
Normal file
279
src/routes/blog/html-in-css/+page.svx
Normal file
@@ -0,0 +1,279 @@
|
|||||||
|
---
|
||||||
|
title: "DRY-фреймворк: как сократить HTML-код и писать только на CSS"
|
||||||
|
---
|
||||||
|
|
||||||
|
<div class="text-xs">
|
||||||
|
2024-08-01
|
||||||
|
</div>
|
||||||
|
|
||||||
|
# {title}
|
||||||
|
|
||||||
|
## О проекте
|
||||||
|
|
||||||
|
### Принцип DRY
|
||||||
|
|
||||||
|
Представьте: у вас есть страница со скопированным кодом. Если заменить одну строку в CSS, придется вносить изменения в зависимые блоки. А если вдруг забыли их поменять, то, скорее всего, вас будет ждать долгий поиск и мучительное решение проблемы.
|
||||||
|
|
||||||
|
Чтобы предотвратить ошибку, я решил придерживаться главной заповеди чистого кода — DRY, Don’t Repeat Yourself. Принцип помогает сократить повторяющийся код за счет разделения проекта на мелкие независимые модули. Туда можно с легкостью вносить новые изменения — другие блоки не пострадают.
|
||||||
|
|
||||||
|
DRY замотивировал меня разработать такой проект, в котором принцип осуществлялся на 110%. Изначально, чтобы сверстать страницу, нужно было описать структуру документа в HTML, а потом — в селекторах на CSS. Приходилось проделывать работу дважды.
|
||||||
|
|
||||||
|
Стало интересно, что будет, если поменять структуру документа. Перестать тратить время на написание кода в двух местах и сконцентрироваться только на CSS? В своем фреймворке я оптимизировал структуру и сделал ее намного удобнее (вот только для кого?).
|
||||||
|
|
||||||
|
### Работа с фреймворком
|
||||||
|
|
||||||
|
Кратко расскажу о принципе работы фреймворка. HTML in CSS — это способ избежать повторяющийся код. В нем можно писать только на CSS, HTML будет генерироваться самостоятельно.
|
||||||
|
|
||||||
|
Перед вами стандартная страница с версткой:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
h1#title {
|
||||||
|
font-size: x-large;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
main#main {
|
||||||
|
color: purple;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1 id="title">Заголовок</h1>
|
||||||
|
|
||||||
|
<main id="main">
|
||||||
|
Крутой контент
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
```
|
||||||
|
|
||||||
|
Синьоры и сеньориты среди вас, вероятно, заметили, что лишняя информация находится:
|
||||||
|
- в HTML — `h1 id="title"`;
|
||||||
|
- в CSS — `h1#title {`;
|
||||||
|
- в HTML — `main id="main"`;
|
||||||
|
- в CSS — `main#main`.
|
||||||
|
|
||||||
|
HTML полностью повторяет код в CSS, поэтому я решил убрать содержимое тега `<body>`. Без него мы не потеряем ничего, кроме контента:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
h1#title {
|
||||||
|
font-size: x-large;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#title:before {
|
||||||
|
content: "Заголовок";
|
||||||
|
}
|
||||||
|
|
||||||
|
main#main {
|
||||||
|
color: purple;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main:before {
|
||||||
|
content: "Крутой контент";
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body></body>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Особенности фреймворка
|
||||||
|
|
||||||
|
HTML in CSS можно использовать практически на любом коде сайта, но есть несколько оговорок.
|
||||||
|
|
||||||
|
Селекторы могут создать только один элемент и не более — двух одинаковых id не бывает.
|
||||||
|
|
||||||
|
```css
|
||||||
|
#parent > #child {}
|
||||||
|
```
|
||||||
|
|
||||||
|
Текстовое содержание должно находиться в псевдоэлементах, иначе не получится передать внутреннее содержимое тега через CSS.
|
||||||
|
|
||||||
|
```css
|
||||||
|
#kopyl-link::before {
|
||||||
|
content: "Ссылка на наш сайт";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Страница может запускаться только в рантайме, поэтому о SEO-оптимизации стоит забыть. Это норма для многих современных фреймворков, если не говорить об их SSR-вариациях.
|
||||||
|
|
||||||
|
## Работа с элементами
|
||||||
|
|
||||||
|
О проекте и его особенностях мы узнали. Теперь рассмотрим, как использовать ссылки, вложенность, порядок и другие функции с помощью инструмента.
|
||||||
|
|
||||||
|
<div class="border-l border-l-slate-400 p-6 bg-slate-900">
|
||||||
|
У фреймворка есть «козырь в рукаве» — это селекторы атрибутов. Он предлагает широкий выбор элементов для разработки: от картинок и видео до айфреймов. Мы часто будем использовать его в наших примерах.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
### Ссылки
|
||||||
|
|
||||||
|
<div class="grid md:grid-cols-2 gap-4 my-6">
|
||||||
|
<div>
|
||||||
|
|
||||||
|
**CSS код**
|
||||||
|
|
||||||
|
```css
|
||||||
|
a#kopyl-link[href="kopyl.dev"] {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#kopyl-link::before {
|
||||||
|
content: "Ссылка на наш сайт";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
|
||||||
|
**Сгенерированный HTML**
|
||||||
|
|
||||||
|
```html
|
||||||
|
<a
|
||||||
|
id="kopyl-link"
|
||||||
|
href="kopyl.dev"
|
||||||
|
></a>
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
А если хотите, чтобы ссылка открывалась в новой вкладке?
|
||||||
|
|
||||||
|
<div class="grid md:grid-cols-2 gap-4 my-6">
|
||||||
|
<div>
|
||||||
|
|
||||||
|
**CSS код**
|
||||||
|
|
||||||
|
```css
|
||||||
|
a#kopyl-link[href="kopyl.dev"][target="_blank"] {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
|
||||||
|
**Сгенерированный HTML**
|
||||||
|
|
||||||
|
```html
|
||||||
|
<a
|
||||||
|
id="kopyl-link"
|
||||||
|
href="kopyl.dev"
|
||||||
|
target="_blank"
|
||||||
|
></a>
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
### Вложенность
|
||||||
|
|
||||||
|
<div class="grid md:grid-cols-2 gap-4 my-6">
|
||||||
|
<div>
|
||||||
|
|
||||||
|
**CSS код**
|
||||||
|
|
||||||
|
```css
|
||||||
|
#parent {
|
||||||
|
width: 200px;
|
||||||
|
height: 200px;
|
||||||
|
background-color: blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
#parent > #child {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
background-color: green;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
|
||||||
|
**Сгенерированный HTML**
|
||||||
|
|
||||||
|
```html
|
||||||
|
<div id="parent">
|
||||||
|
<div id="child"></div>
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
### Порядок
|
||||||
|
|
||||||
|
Используя селекторы псевдоклассов `:nth-child`, `:first-child`, `:last-child`, можно задать порядок элементов.
|
||||||
|
|
||||||
|
<div class="grid md:grid-cols-2 gap-4 my-6">
|
||||||
|
<div>
|
||||||
|
|
||||||
|
**CSS код**
|
||||||
|
|
||||||
|
```css
|
||||||
|
#parent > #foo:last-child {
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#foo::before {
|
||||||
|
content: "Я последний";
|
||||||
|
}
|
||||||
|
|
||||||
|
#parent > #bar:first-child {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#bar::before {
|
||||||
|
content: "А я первый";
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
|
||||||
|
**Сгенерированный HTML**
|
||||||
|
|
||||||
|
```html
|
||||||
|
<div id="parent">
|
||||||
|
<div id="bar"></div>
|
||||||
|
<div id="foo"></div>
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
### JavaScript
|
||||||
|
|
||||||
|
К сожалению, фреймворк не поддерживает JavaScript, но это не мешает подключить к нему внешний файл — `main.js`. Да и никто не запретит нам описывать селекторы для тегов `script` и добавлять туда атрибуты.
|
||||||
|
|
||||||
|
```css
|
||||||
|
script#my-script[src="/main.js"] {}
|
||||||
|
```
|
||||||
|
|
||||||
|
В `main.js` можно использовать любой интерактив, который нужен сайту, — например, обработку событий, клиентский роутер и другие.
|
||||||
|
|
||||||
|
## Заключение
|
||||||
|
|
||||||
|
Возможно, некоторые уже захотели переписать свой продакшн-сайт на HTML in CSS, но мне жаль вас огорчать — на самом деле это фреймворк-шутка.
|
||||||
|
|
||||||
|
Одним вечером мне стало интересно, как парсится CSS и как выглядит его структура. В процессе изучения пришла в голову идея создать свой фреймворк. Как говорится, закрепил теорию практикой. Кстати, фреймворк занимает около 120 строк неубористого кода.
|
||||||
|
|
||||||
|
<div class="py-4 flex gap-4">
|
||||||
|
<a
|
||||||
|
href="https://habr.com/ru/companies/kopyl/articles/832868/"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
Репозиторий проекта
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="https://habr.com/ru/companies/kopyl/articles/832868/"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
Обсудить на Хабре
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
2
static/robots.txt
Normal file
2
static/robots.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
User-agent: *
|
||||||
|
Disallow: /blog/
|
||||||
@@ -1,9 +1,14 @@
|
|||||||
import adapter from '@sveltejs/adapter-node';
|
import adapter from '@sveltejs/adapter-node';
|
||||||
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
|
||||||
|
import {mdsvex} from "mdsvex";
|
||||||
|
|
||||||
/** @type {import('@sveltejs/kit').Config} */
|
/** @type {import('@sveltejs/kit').Config} */
|
||||||
const config = {
|
const config = {
|
||||||
preprocess: vitePreprocess(),
|
extensions: ['.svelte', '.svx'],
|
||||||
|
preprocess: [
|
||||||
|
vitePreprocess(),
|
||||||
|
mdsvex(),
|
||||||
|
],
|
||||||
kit: {
|
kit: {
|
||||||
adapter: adapter()
|
adapter: adapter()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/** @type {import('tailwindcss').Config} */
|
/** @type {import('tailwindcss').Config} */
|
||||||
export default {
|
export default {
|
||||||
content: ['./src/**/*.{html,js,svelte,ts}'],
|
content: ['./src/**/*.{html,js,svelte,ts,svx}'],
|
||||||
theme: {
|
theme: {
|
||||||
extend: {},
|
extend: {},
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user