Compare commits
7 commits
d39b85fbc7
...
2318a645ce
Author | SHA1 | Date | |
---|---|---|---|
2318a645ce | |||
4869352450 | |||
4bd4d08f06 | |||
0efc5a3362 | |||
e5c924f73b | |||
29102b4ad6 | |||
6d9e05c3e8 |
14 changed files with 1226 additions and 5451 deletions
6455
package-lock.json
generated
6455
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -10,8 +10,8 @@
|
||||||
"astro": "astro"
|
"astro": "astro"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"astro": "^2.9.0",
|
"astro": "^2.10.5",
|
||||||
"astro-compress": "^1.1.50",
|
"astro-compress": "^2.0.5",
|
||||||
"intl": "^1.2.5",
|
"intl": "^1.2.5",
|
||||||
"less": "^4.1.3",
|
"less": "^4.1.3",
|
||||||
"reading-time": "^1.5.0",
|
"reading-time": "^1.5.0",
|
||||||
|
|
BIN
public/assets/20220629-mvsp/devtools.jpg
Normal file
BIN
public/assets/20220629-mvsp/devtools.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
Binary file not shown.
Before Width: | Height: | Size: 229 KiB |
|
@ -19,6 +19,7 @@ const {
|
||||||
<div class="card card-elevated" id={post.slug}>
|
<div class="card card-elevated" id={post.slug}>
|
||||||
<Article
|
<Article
|
||||||
PostContent={PostContent}
|
PostContent={PostContent}
|
||||||
|
slug={post.slug}
|
||||||
title={title}
|
title={title}
|
||||||
description={description}
|
description={description}
|
||||||
readingTime={readingTime}
|
readingTime={readingTime}
|
||||||
|
|
|
@ -35,6 +35,8 @@ const {
|
||||||
@icon-size: 1.5rem;
|
@icon-size: 1.5rem;
|
||||||
|
|
||||||
li {
|
li {
|
||||||
|
height: fit-content;
|
||||||
|
|
||||||
a {
|
a {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
|
52
src/components/PageCtrlBtn.astro
Normal file
52
src/components/PageCtrlBtn.astro
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
---
|
||||||
|
import Icon from './Icon.astro';
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
btnKind: 'prev' | 'pagenum' | 'next';
|
||||||
|
url?: string | undefined;
|
||||||
|
num?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { btnKind, url, num = 1 } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
<a href={url ?? 'javascript:void(0)'} class={btnKind}>
|
||||||
|
{
|
||||||
|
btnKind === 'pagenum' ? <span class="pagenum">{num}</span> :
|
||||||
|
btnKind === 'prev' ? <Icon code="" /> :
|
||||||
|
btnKind === 'next' ? <Icon code="" /> :
|
||||||
|
""
|
||||||
|
}
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
a {
|
||||||
|
@size: 1.1rem;
|
||||||
|
@color: var(--fg);
|
||||||
|
|
||||||
|
width: @size;
|
||||||
|
height: @size;
|
||||||
|
box-sizing: content-box;
|
||||||
|
|
||||||
|
font-size: @size;
|
||||||
|
padding: 0.625rem;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
color: @color;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: @color;
|
||||||
|
|
||||||
|
background: var(--accent-bg);
|
||||||
|
border-radius: var(--bdrs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagenum {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
</style>
|
82
src/components/ScrollToTop.astro
Normal file
82
src/components/ScrollToTop.astro
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
---
|
||||||
|
import Icon from "./Icon.astro";
|
||||||
|
---
|
||||||
|
|
||||||
|
<div id="scroll-to-top" data-show="0">
|
||||||
|
<a href="#">
|
||||||
|
<Icon code="" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
@size: 2.25rem;
|
||||||
|
@font: 1.50rem;
|
||||||
|
|
||||||
|
div {
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
&[data-show="0"] a {
|
||||||
|
height: 0;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.2s ease, height 0.2s step-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-show="1"] a {
|
||||||
|
height: @size;
|
||||||
|
opacity: 1;
|
||||||
|
transition: opacity 0.2s ease, height 0.2s step-start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0.5rem;
|
||||||
|
right: 0.625rem;
|
||||||
|
|
||||||
|
display: inline-flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0.25rem;
|
||||||
|
|
||||||
|
width: @size;
|
||||||
|
height: @size;
|
||||||
|
border-radius: @size;
|
||||||
|
font-size: @font;
|
||||||
|
|
||||||
|
background: var(--accent-bg);
|
||||||
|
color: var(--fg);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: var(--bg-sec);
|
||||||
|
color: var(--fg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const stt = document.getElementById('scroll-to-top')
|
||||||
|
const doc = document.documentElement
|
||||||
|
|
||||||
|
let scrollPos = 0
|
||||||
|
let ticking = false
|
||||||
|
|
||||||
|
const handler = (pos: number) => {
|
||||||
|
if (pos > doc.clientHeight / 2) {
|
||||||
|
stt.dataset.show = '1'
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
stt.dataset.show = '0'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addEventListener('scroll', () => {
|
||||||
|
scrollPos = window.scrollY
|
||||||
|
if (!ticking) {
|
||||||
|
window.requestAnimationFrame(() => {
|
||||||
|
handler(scrollPos)
|
||||||
|
ticking = false
|
||||||
|
})
|
||||||
|
ticking = true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
19
src/content/blog/20220629-mvsp.md
Normal file
19
src/content/blog/20220629-mvsp.md
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
---
|
||||||
|
comments: dcat09/18
|
||||||
|
---
|
||||||
|
|
||||||
|
# Начинающему фронтендеру: margin vs padding
|
||||||
|
|
||||||
|
Раньше я не понимал разницы между margin и padding, и ставил их в CSS наугад, проверяя результат.
|
||||||
|
На StackOverflow объяснение было так себе, да и инглиш я тогда знал тоже так себе.
|
||||||
|
|
||||||
|
Помог мне Chrome, а точнее инструменты разработчика. Внизу вкладки "Стили" есть наглядная визуализация отступов цветными прямоугольниками.
|
||||||
|
|
||||||
|
![](/assets/20220629-mvsp/devtools.jpg)
|
||||||
|
|
||||||
|
- Вокруг содержимого элемента -- **padding**, ограничивающий текст от рамки
|
||||||
|
- После него -- **border**, т.е. сама рамка
|
||||||
|
- После border -- **margin**, ограничивающий элемент от других элементов
|
||||||
|
|
||||||
|
А посмотреть всё это в интерактивном виде можно на [странице на Codeberg Pages](https://darkcat09.codeberg.page/margin-vs-padding).
|
||||||
|
Исходники: [Codeberg](https://codeberg.org/DarkCat09/margin-vs-padding) | [Gitea](https://git.dc09.ru/DarkCat09/margin-vs-padding).
|
28
src/content/blog/20220729-xdt.md
Normal file
28
src/content/blog/20220729-xdt.md
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
---
|
||||||
|
comments: dcat09/37
|
||||||
|
---
|
||||||
|
|
||||||
|
# Технологии XDT, или YouTube всё знает...
|
||||||
|
|
||||||
|
Смотрел я на СТСе Гарри Поттера.
|
||||||
|
На следующий день в рекомендациях ютуба появились видео на тему вышеуказанного фильма, которые я не искал примерно год.
|
||||||
|
Как? Ведь тогда установлены были не официальные сервисы, а MicroG.
|
||||||
|
|
||||||
|
Где-то на хабре в комментах под статьёй то ли про телеметрию, то ли про рекламу, был такой вариант: генерация высокочастотных звуков при трансляции телепередач, чтобы наши девайсы отслеживали их и понимали, что мы смотрим. И на основе этого предлагать таргетированную рекламу.
|
||||||
|
<s>Лишь бы этим не воспользовались. Или уже?</s>
|
||||||
|
|
||||||
|
**Upd:**
|
||||||
|
Технология называется [Cross-device tracking (CDT, XDT)](https://en.m.wikipedia.org/wiki/Cross-device_tracking).
|
||||||
|
К ней относится аналитика, обычно с целью показа рекламы, которая, вместо сохранения идентификатора в одной сессии браузера или его привязки к одному IP-адресу, может передавать рекламный ID между устройствами.
|
||||||
|
Внедряют почти все, кому не лень.
|
||||||
|
|
||||||
|
- Самый простой способ -- отслеживание **залогиненных пользователей**.
|
||||||
|
На сайте у человека есть аккаунт, в который он входит с разных устройств.
|
||||||
|
Таким образом можно сохранять список устройств, далее - делать что угодно.
|
||||||
|
"Рекламный идентификатор" у Google является ярким примером такого XDT.
|
||||||
|
|
||||||
|
- Способ сложнее, о котором я и рассказывал -- **использование ультразвука** для передачи информации между устройствами.
|
||||||
|
Лидирует в этом варианте XDT комания SilverPush, у которой ещё и патент на эту технологию.
|
||||||
|
Для защиты можно использовать приложение [PilferShushJammer](https://github.com/kaputnikGo/PilferShushJammer).
|
||||||
|
|
||||||
|
За информацию большое спасибо [@nvrm17](https://t.me/nvrm17)
|
|
@ -1,4 +1,5 @@
|
||||||
---
|
---
|
||||||
|
draft: true
|
||||||
comments: dcat09/1
|
comments: dcat09/1
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -92,5 +93,5 @@ echo('Your ID: ' . $uid);
|
||||||
Скомбинированный вариант: временный секретный ключ, на основе которого генерируется одноразовый код, отправляемый по E-Mail/SMS. Ключ не хранится в БД, плюс он временный, взлом почти невозможен.
|
Скомбинированный вариант: временный секретный ключ, на основе которого генерируется одноразовый код, отправляемый по E-Mail/SMS. Ключ не хранится в БД, плюс он временный, взлом почти невозможен.
|
||||||
|
|
||||||
## 2FA
|
## 2FA
|
||||||
Двухфакторная аутентификация, она же 2FA, -- мощный механизм защиты учётной записи.
|
Двухфакторная аутентификация, она же 2FA, -- мощный механизм защиты учётной записи.
|
||||||
// TODO: Дописать
|
// TODO: Дописать
|
||||||
|
|
|
@ -4,11 +4,6 @@ comments: dcat09/338
|
||||||
|
|
||||||
# Коротко о разработке ПО сейчас
|
# Коротко о разработке ПО сейчас
|
||||||
|
|
||||||
_[Оригинальный текст](https://factoryfactoryfactory.net)_
|
|
||||||
_Перевод [DarkCat09](https://dc09.ru)_
|
|
||||||
|
|
||||||
***
|
|
||||||
|
|
||||||
Представим, что я решил сделать подставку для специй.
|
Представим, что я решил сделать подставку для специй.
|
||||||
|
|
||||||
Я уже имел дело с небольшими проектами по работе с деревом, и хорошо представляю, что мне необходимо: древесный материал и несколько основных инструментов: рулетка, уровень, пила и молоток.
|
Я уже имел дело с небольшими проектами по работе с деревом, и хорошо представляю, что мне необходимо: древесный материал и несколько основных инструментов: рулетка, уровень, пила и молоток.
|
||||||
|
@ -65,7 +60,7 @@ _Перевод [DarkCat09](https://dc09.ru)_
|
||||||
|
|
||||||
— Внимательно слушаю.
|
— Внимательно слушаю.
|
||||||
|
|
||||||
— Когда мы шагнули назад и посмотрели на всю картину инфраструктуры строительных инструментов, мы определили, что люди разочарованы в необходимости управлять фабрикой фабрик, как и производимой ею фабрикой. Что довольно обременительно, когда вы оперируете по такому же сценарию ещё и фабрикой фабрик рулеток, фабрикой фабрик уровней, фабрикой фабрик пил, не говоря уже о холдинге компаний по производству древесного материала. Когда мы здраво оценили ситуацию, мы поняли, что вышеописанное слишком сложно для тех, кому просто хочется сделать подставку для специй.
|
— Когда мы шагнули назад и посмотрели на всю картину инфраструктуры строительных инструментов, мы определили, что люди разочарованы в необходимости управлять фабрикой фабрик, как и производимой ею фабрикой. Это довольно обременительно, когда вы оперируете по такому же сценарию ещё и фабрикой фабрик рулеток, фабрикой фабрик уровней, фабрикой фабрик пил, не говоря уже о холдинге компаний по производству древесного материала. Когда мы здраво оценили ситуацию, мы поняли, что вышеописанное слишком сложно для тех, кому просто хочется сделать подставку для специй.
|
||||||
|
|
||||||
— Да, без шуток, абсолютно верно.
|
— Да, без шуток, абсолютно верно.
|
||||||
|
|
||||||
|
@ -84,3 +79,8 @@ _Перевод [DarkCat09](https://dc09.ru)_
|
||||||
— Что будет очень полезно для вас!
|
— Что будет очень полезно для вас!
|
||||||
|
|
||||||
— У этой штуки же есть документация, да?
|
— У этой штуки же есть документация, да?
|
||||||
|
|
||||||
|
***
|
||||||
|
|
||||||
|
_[Оригинальный текст](https://factoryfactoryfactory.net) написан Benji Smith,_
|
||||||
|
_переведён [DarkCat09](https://dc09.ru)_
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
import Layout from "./Layout.astro";
|
import Layout from "./Layout.astro";
|
||||||
import NavMenu from "./NavMenu.astro";
|
import NavMenu from "./NavMenu.astro";
|
||||||
import MenuItem from "../components/MenuItem.astro";
|
import MenuItem from "../components/MenuItem.astro";
|
||||||
|
import ScrollToTop from "../components/ScrollToTop.astro";
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
title: string;
|
title: string;
|
||||||
|
@ -14,6 +15,7 @@ const { title, description, mainpage = false } = Astro.props;
|
||||||
|
|
||||||
<Layout title={"Blog | " + title} description={description}>
|
<Layout title={"Blog | " + title} description={description}>
|
||||||
<slot name="metadata" slot="metadata" />
|
<slot name="metadata" slot="metadata" />
|
||||||
|
<ScrollToTop />
|
||||||
<NavMenu>
|
<NavMenu>
|
||||||
{
|
{
|
||||||
mainpage ?
|
mainpage ?
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
---
|
---
|
||||||
import BlogLayout from "../../layouts/BlogLayout.astro";
|
import BlogLayout from "../../layouts/BlogLayout.astro";
|
||||||
import ArticleCard from "../../components/ArticleCard.astro";
|
import ArticleCard from "../../components/ArticleCard.astro";
|
||||||
|
import PageCtrlBtn from "../../components/PageCtrlBtn.astro";
|
||||||
|
|
||||||
import { getCollection } from "astro:content";
|
import { getCollection } from "astro:content";
|
||||||
|
import { Page } from "astro";
|
||||||
|
|
||||||
export async function getStaticPaths({ paginate }) {
|
export async function getStaticPaths({ paginate }) {
|
||||||
const POSTS_ON_PAGE = 15;
|
const POSTS_ON_PAGE = 15;
|
||||||
|
@ -19,7 +21,7 @@ export async function getStaticPaths({ paginate }) {
|
||||||
return paginate(posts, { pageSize: POSTS_ON_PAGE });
|
return paginate(posts, { pageSize: POSTS_ON_PAGE });
|
||||||
}
|
}
|
||||||
|
|
||||||
const { page } = Astro.props;
|
const page: Page = Astro.props.page;
|
||||||
const description =
|
const description =
|
||||||
"DarkCat09's blog. " +
|
"DarkCat09's blog. " +
|
||||||
"Reading a QR code without a phone, " +
|
"Reading a QR code without a phone, " +
|
||||||
|
@ -35,6 +37,11 @@ const description =
|
||||||
<div id="articles">
|
<div id="articles">
|
||||||
{page.data.map(({ post }) => <ArticleCard post={post} />)}
|
{page.data.map(({ post }) => <ArticleCard post={post} />)}
|
||||||
</div>
|
</div>
|
||||||
|
<div id="page-ctrl">
|
||||||
|
<PageCtrlBtn btnKind="prev" url={page.url.prev} />
|
||||||
|
<PageCtrlBtn btnKind="pagenum" num={page.currentPage} />
|
||||||
|
<PageCtrlBtn btnKind="next" url={page.url.next} />
|
||||||
|
</div>
|
||||||
</BlogLayout>
|
</BlogLayout>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
|
@ -46,4 +53,12 @@ const description =
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: @body-padding + @main-padding;
|
gap: @body-padding + @main-padding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#page-ctrl {
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Add table
Reference in a new issue