Установка Quartz
Клонирование quartz
git clone https://github.com/jackyzha0/quartz.git hub.zlonov.ru
cd hub.zlonov.ru
npm i
npx quartz create
Выбираем последовательно опции:
- Empty Quartz
- Treat links as shortest path (for most Obsidian vaults)
Создание репозитория
https://quartz.jzhao.xyz/setting-up-your-GitHub-repository
Then, create a new repository on GitHub.com. Do not initialize the new repository with README, license, or gitignore files.
На выходе: https://github.com/zlonov/hub.zlonov.ru.git
Настройка репозитория
https://quartz.jzhao.xyz/setting-up-your-GitHub-repository
Отредактировать файл hub.zlonov.ru/.git/config
[core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true ignorecase = true precomposeunicode = true [remote "origin"] url = https://github.com/zlonov/hub.zlonov.ru.git fetch = +refs/heads/*:refs/remotes/origin/* [branch "v4"] remote = origin merge = refs/heads/v4 [remote "upstream"] url = https://github.com/jackyzha0/quartz.git fetch = +refs/heads/*:refs/remotes/upstream/*
To verify that you set the remote URL correctly, run the following command.
git remote -v
Then, you can sync the content to upload it to your repository.
npx quartz sync --no-pull
Добавление репозитория в GitHub Desktop
Add
→ Add Existing Repository...
→ Choose...
→ hub.zlonov.ru
Commit to v4
Добавление внешнего подмодуля
https://git-scm.com/book/ru/v2/Инструменты-Git-Подмодули
Удалить папку hub.zlonov.ru/content/
Добавить подмодуль
git submodule add https://gitflic.ru/project/zlonov/catalog.git content
Отправить обновление в репозиторий через GitHub Desktop:
Commit to v4
с комментарием “Добавлен подмодуль”
Можно убедиться, что подмодуль корректно добавлен: https://github.com/zlonov/hub.zlonov.ru
Обновление контента и Хаба
Обновление данных в подмодуле
Один раз создаём удобный псевдоним для проверки и обновления подмодуля:
git config alias.sup 'submodule update --remote --merge'
Теперь вместо этой длинной команды можно писать просто: git sup
- Вносим изменения
- Выполняем в GitHub Desktop
Commit to master
иPush
- Обновляем репозиторий с учётом изменений подмодуля
git sup
- Выполняем в GitHub Desktop
Commit to v4
иPush
Можно посмотреть как выполняются Actions: https://github.com/zlonov/hub.zlonov.ru/actions
Вариант для командной строки: https://git-scm.com/book/ru/v2/Основы-Git-Запись-изменений-в-репозиторий
- Вносим изменения
- Выполняем в GitHub Desktop
Commit to master
иPush
- Обновляем репозиторий с учётом изменений подмодуля
git sup
- Выполняем
git commit -a -m "Update content"
(благодаря опции-a
не нужно выполнятьgit add ИМЯ.ФАЙЛА
) - Отправляем изменения на сервер
git push
Вариант для командной строки с использованием псевдонимов https://git-scm.com/book/ru/v2/Основы-Git-Псевдонимы-в-Git
- Один раз создаём короткий псевдоним:
git config alias.up '!git submodule update --remote --merge && git commit -a -m "Update content" && git push'
- Далее его используем:
git up
Настройки после клонирования на другой компьютер
Сначала инициировать:
npm i
Локальный предпросмотр Хаба
npx quartz build --serve
Сбор статистики
Счётчики
Umami
<script defer src="https://eu.umami.is/script.js" data-website-id="e080cafe-f61b-48c1-9cb2-0d744e043a53"></script>
<!-- Google tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-120278956-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-120278956-1');
</script>
Яндекс старый
<!-- Yandex.Metrika counter -->
<script src="https://mc.yandex.ru/metrika/watch.js" type="text/javascript" ></script>
<script type="text/javascript" >
try {
var yaCounter96251472 = new Ya.Metrika({
id:96251472,
clickmap:true,
trackLinks:true,
accurateTrackBounce:true
});
} catch(e) { }
</script>
<!-- /Yandex.Metrika counter -->
Яндекс новый (не ясно, как установить)
<!-- Yandex.Metrika counter -->
<script type="text/javascript" >
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();
for (var j = 0; j < document.scripts.length; j++) {if (document.scripts[j].src === r) { return; }}
k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(96251472, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true
});
</script>
<noscript><div><img src="https://mc.yandex.ru/watch/96251472" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->
Дефолтные способы вызовов
if (cfg.analytics?.provider === "google") {
const tagId = cfg.analytics.tagId
staticResources.js.push({
src: `https://www.googletagmanager.com/gtag/js?id=${tagId}`,
contentType: "external",
loadTime: "afterDOMReady",
})
componentResources.afterDOMLoaded.push(`
window.dataLayer = window.dataLayer || [];
function gtag() { dataLayer.push(arguments); }
gtag("js", new Date());
gtag("config", "${tagId}", { send_page_view: false });
document.addEventListener("nav", () => {
gtag("event", "page_view", {
page_title: document.title,
page_location: location.href,
});
});`)
} else if (cfg.analytics?.provider === "plausible") {
const plausibleHost = cfg.analytics.host ?? "https://plausible.io"
componentResources.afterDOMLoaded.push(`
const plausibleScript = document.createElement("script")
plausibleScript.src = "${plausibleHost}/js/script.manual.js"
plausibleScript.setAttribute("data-domain", location.hostname)
plausibleScript.defer = true
document.head.appendChild(plausibleScript)
window.plausible = window.plausible || function() { (window.plausible.q = window.plausible.q || []).push(arguments) }
document.addEventListener("nav", () => {
plausible("pageview")
})
`)
} else if (cfg.analytics?.provider === "umami") {
componentResources.afterDOMLoaded.push(`
const umamiScript = document.createElement("script")
umamiScript.src = "https://analytics.umami.is/script.js"
umamiScript.setAttribute("data-website-id", "${cfg.analytics.websiteId}")
umamiScript.async = true
document.head.appendChild(umamiScript)
`)
}
Вариант со старым счётчиком Яндекса, который должен сработать (не работает)
else if (cfg.analytics?.provider === "yandex") {
const ymId = cfg.analytics.ymId
staticResources.js.push({
src: `https://mc.yandex.ru/metrika/watch.js`,
contentType: "external",
loadTime: "afterDOMReady",
})
componentResources.afterDOMLoaded.push(`
try {
var yaCounter96251472 = new Ya.Metrika({
id:${ymId},
clickmap:true,
trackLinks:true,
accurateTrackBounce:true
});
} catch(e) { };
`)
}
Вариант через вставку в Head.tsx (не сработало)
Создаём константу:
const YaMetrics = `<!-- Yandex.Metrika counter --> <script type="text/javascript" > (function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)}; m[i].l=1*new Date(); for (var j = 0; j < document.scripts.length; j++) {if (document.scripts[j].src === r) { return; }} k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)}) (window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym"); ym(96251472, "init", { clickmap:true, trackLinks:true, accurateTrackBounce:true }); </script> <noscript><div><img src="https://mc.yandex.ru/watch/96251472" style="position:absolute; left:-9999px;" alt="" /></div></noscript> <!-- /Yandex.Metrika counter -->`
Добавляем её в вывод в составе результата
export default (() => {
function Head({ cfg, fileData, externalResources }: QuartzComponentProps) {
const title = fileData.frontmatter?.title ?? "Untitled"
const description = fileData.description?.trim() ?? "No description provided"
const { css, js } = externalResources
const url = new URL(`https://${cfg.baseUrl ?? "example.com"}`)
const path = url.pathname as FullSlug
const baseDir = fileData.slug === "404" ? path : pathToRoot(fileData.slug!)
const iconPath = joinSegments(baseDir, "static/icon.png")
const ogImagePath = `https://${cfg.baseUrl}/static/og-image.png`
const YaMetrics = `<!-- Yandex.Metrika counter --> <script type="text/javascript" > (function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)}; m[i].l=1*new Date(); for (var j = 0; j < document.scripts.length; j++) {if (document.scripts[j].src === r) { return; }} k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)}) (window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym"); ym(96251472, "init", { clickmap:true, trackLinks:true, accurateTrackBounce:true }); </script> <noscript><div><img src="https://mc.yandex.ru/watch/96251472" style="position:absolute; left:-9999px;" alt="" /></div></noscript> <!-- /Yandex.Metrika counter -->`
return (
<head>
<title>{title}</title>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta property="og:title" content={title} />
<meta property="og:description" content={description} />
{cfg.baseUrl && <meta property="og:image" content={ogImagePath} />}
<meta property="og:width" content="1200" />
<meta property="og:height" content="675" />
<link rel="icon" href={iconPath} />
<meta name="description" content={description} />
<meta name="generator" content="Quartz" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" />
{css.map((href) => (
<link key={href} href={href} rel="stylesheet" type="text/css" spa-preserve />
))}
{js
.filter((resource) => resource.loadTime === "beforeDOMReady")
.map((res) => JSResourceToScriptElement(res, true))}
{YaMetrics}
</head>
)
}
return Head
})
Альтернатива на umami:
provider: "umami", websiteId: "e080cafe-f61b-48c1-9cb2-0d744e043a53",