Skip to content

Commit cc99824

Browse files
committed
update umami with upstream
1 parent da213a6 commit cc99824

3 files changed

Lines changed: 102 additions & 67 deletions

File tree

quartz.config.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@ const config: QuartzConfig = {
1414
enablePopovers: true,
1515
analytics: {
1616
provider: "umami",
17-
websiteId: "b25a1826-6c9f-4a59-8306-e2425efa4781",
18-
host: "https://cloud.umami.is"
17+
websiteId: "b25a1826-6c9f-4a59-8306-e2425efa4781"
1918
},
2019
locale: "zh-CN",
2120
baseUrl: "virgiling.wiki",

quartz/plugins/emitters/componentResources.ts

Lines changed: 67 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,12 @@ import styles from "../../styles/custom.scss"
99
import popoverStyle from "../../components/styles/popover.scss"
1010
import { BuildCtx } from "../../util/ctx"
1111
import { QuartzComponent } from "../../components/types"
12-
import { googleFontHref, joinStyles, processGoogleFonts } from "../../util/theme"
12+
import {
13+
googleFontHref,
14+
googleFontSubsetHref,
15+
joinStyles,
16+
processGoogleFonts,
17+
} from "../../util/theme"
1318
import { Features, transform } from "lightningcss"
1419
import { transform as transpile } from "esbuild"
1520
import { write } from "./helpers"
@@ -83,50 +88,50 @@ function addGlobalPageResources(ctx: BuildCtx, componentResources: ComponentReso
8388
if (cfg.analytics?.provider === "google") {
8489
const tagId = cfg.analytics.tagId
8590
componentResources.afterDOMLoaded.push(`
86-
const gtagScript = document.createElement("script")
87-
gtagScript.src = "https://www.googletagmanager.com/gtag/js?id=${tagId}"
88-
gtagScript.defer = true
89-
document.head.appendChild(gtagScript)
90-
91-
window.dataLayer = window.dataLayer || [];
92-
function gtag() { dataLayer.push(arguments); }
93-
gtag("js", new Date());
94-
gtag("config", "${tagId}", { send_page_view: false });
95-
96-
document.addEventListener("nav", () => {
97-
gtag("event", "page_view", {
98-
page_title: document.title,
99-
page_location: location.href,
91+
const gtagScript = document.createElement('script');
92+
gtagScript.src = 'https://www.googletagmanager.com/gtag/js?id=${tagId}';
93+
gtagScript.defer = true;
94+
gtagScript.onload = () => {
95+
window.dataLayer = window.dataLayer || [];
96+
function gtag() {
97+
dataLayer.push(arguments);
98+
}
99+
gtag('js', new Date());
100+
gtag('config', '${tagId}', { send_page_view: false });
101+
gtag('event', 'page_view', { page_title: document.title, page_location: location.href });
102+
document.addEventListener('nav', () => {
103+
gtag('event', 'page_view', { page_title: document.title, page_location: location.href });
100104
});
101-
});`)
105+
};
106+
107+
document.head.appendChild(gtagScript);
108+
`)
102109
} else if (cfg.analytics?.provider === "plausible") {
103110
const plausibleHost = cfg.analytics.host ?? "https://plausible.io"
104111
componentResources.afterDOMLoaded.push(`
105-
const plausibleScript = document.createElement("script")
106-
plausibleScript.src = "${plausibleHost}/js/script.manual.js"
107-
plausibleScript.setAttribute("data-domain", location.hostname)
108-
plausibleScript.defer = true
109-
document.head.appendChild(plausibleScript)
110-
111-
window.plausible = window.plausible || function() { (window.plausible.q = window.plausible.q || []).push(arguments) }
112+
const plausibleScript = document.createElement('script');
113+
plausibleScript.src = '${plausibleHost}/js/script.manual.js';
114+
plausibleScript.setAttribute('data-domain', location.hostname);
115+
plausibleScript.defer = true;
116+
plausibleScript.onload = () => {
117+
window.plausible = window.plausible || function () { (window.plausible.q = window.plausible.q || []).push(arguments); };
118+
plausible('pageview');
119+
document.addEventListener('nav', () => {
120+
plausible('pageview');
121+
});
122+
};
112123
113-
document.addEventListener("nav", () => {
114-
plausible("pageview")
115-
})
124+
document.head.appendChild(plausibleScript);
116125
`)
117126
} else if (cfg.analytics?.provider === "umami") {
118127
componentResources.afterDOMLoaded.push(`
119-
const umamiScript = document.createElement("script")
120-
umamiScript.defer = true
121-
umamiScript.src = "${cfg.analytics.host ?? "https://analytics.umami.is"}/script.js"
122-
umamiScript.setAttribute("data-website-id", "${cfg.analytics.websiteId}")
123-
umamiScript.setAttribute("data-auto-track", "false")
124-
umamiScript.defer = true
125-
document.head.appendChild(umamiScript)
128+
const umamiScript = document.createElement("script");
129+
umamiScript.src = "${cfg.analytics.host ?? "https://analytics.umami.is"}/script.js";
130+
umamiScript.setAttribute("data-website-id", "${cfg.analytics.websiteId}");
131+
umamiScript.setAttribute("data-auto-track", "true");
132+
umamiScript.defer = true;
126133
127-
document.addEventListener("nav", () => {
128-
umami.track();
129-
})
134+
document.head.appendChild(umamiScript);
130135
`)
131136
} else if (cfg.analytics?.provider === "goatcounter") {
132137
componentResources.afterDOMLoaded.push(`
@@ -153,29 +158,32 @@ function addGlobalPageResources(ctx: BuildCtx, componentResources: ComponentReso
153158
`)
154159
} else if (cfg.analytics?.provider === "posthog") {
155160
componentResources.afterDOMLoaded.push(`
156-
const posthogScript = document.createElement("script")
161+
const posthogScript = document.createElement("script");
157162
posthogScript.innerHTML= \`!function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.async=!0,p.src=s.api_host+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.toString(1)+".people (stub)"},o="capture identify alias people.set people.set_once set_config register register_once unregister opt_out_capturing has_opted_out_capturing opt_in_capturing reset isFeatureEnabled onFeatureFlags getFeatureFlag getFeatureFlagPayload reloadFeatureFlags group updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures getActiveMatchingSurveys getSurveys onSessionId".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);
158163
posthog.init('${cfg.analytics.apiKey}', {
159164
api_host: '${cfg.analytics.host ?? "https://app.posthog.com"}',
160165
capture_pageview: false,
166+
});
167+
document.addEventListener('nav', () => {
168+
posthog.capture('$pageview', { path: location.pathname });
161169
})\`
162-
document.head.appendChild(posthogScript)
163170
164-
document.addEventListener("nav", () => {
165-
posthog.capture('$pageview', { path: location.pathname })
166-
})
171+
document.head.appendChild(posthogScript);
167172
`)
168173
} else if (cfg.analytics?.provider === "tinylytics") {
169174
const siteId = cfg.analytics.siteId
170175
componentResources.afterDOMLoaded.push(`
171-
const tinylyticsScript = document.createElement("script")
172-
tinylyticsScript.src = "https://tinylytics.app/embed/${siteId}.js?spa"
173-
tinylyticsScript.defer = true
174-
document.head.appendChild(tinylyticsScript)
175-
176-
document.addEventListener("nav", () => {
177-
window.tinylytics.triggerUpdate()
178-
})
176+
const tinylyticsScript = document.createElement('script');
177+
tinylyticsScript.src = 'https://tinylytics.app/embed/${siteId}.js?spa';
178+
tinylyticsScript.defer = true;
179+
tinylyticsScript.onload = () => {
180+
window.tinylytics.triggerUpdate();
181+
document.addEventListener('nav', () => {
182+
window.tinylytics.triggerUpdate();
183+
});
184+
};
185+
186+
document.head.appendChild(tinylyticsScript);
179187
`)
180188
} else if (cfg.analytics?.provider === "cabin") {
181189
componentResources.afterDOMLoaded.push(`
@@ -271,9 +279,16 @@ export const ComponentResources: QuartzEmitterPlugin = () => {
271279
// let the user do it themselves in css
272280
} else if (cfg.theme.fontOrigin === "googleFonts" && !cfg.theme.cdnCaching) {
273281
// when cdnCaching is true, we link to google fonts in Head.tsx
274-
const response = await fetch(googleFontHref(ctx.cfg.configuration.theme))
282+
const theme = ctx.cfg.configuration.theme
283+
const response = await fetch(googleFontHref(theme))
275284
googleFontsStyleSheet = await response.text()
276285

286+
if (theme.typography.title) {
287+
const title = ctx.cfg.configuration.pageTitle
288+
const response = await fetch(googleFontSubsetHref(theme, title))
289+
googleFontsStyleSheet += `\n${await response.text()}`
290+
}
291+
277292
if (!cfg.baseUrl) {
278293
throw new Error(
279294
"baseUrl must be defined when using Google Fonts without cfg.theme.cdnCaching",
@@ -353,6 +368,6 @@ export const ComponentResources: QuartzEmitterPlugin = () => {
353368
content: postscript,
354369
})
355370
},
356-
async *partialEmit() {},
371+
async *partialEmit() { },
357372
}
358-
}
373+
}

quartz/util/theme.ts

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,14 @@ interface Colors {
1818
export type FontSpecification =
1919
| string
2020
| {
21-
name: string
22-
weights?: number[]
23-
includeItalic?: boolean
24-
}
21+
name: string
22+
weights?: number[]
23+
includeItalic?: boolean
24+
}
2525

2626
export interface Theme {
2727
typography: {
28+
title?: FontSpecification
2829
header: FontSpecification
2930
body: FontSpecification
3031
code: FontSpecification
@@ -48,7 +49,10 @@ export function getFontSpecificationName(spec: FontSpecification): string {
4849
return spec.name
4950
}
5051

51-
function formatFontSpecification(type: "header" | "body" | "code", spec: FontSpecification) {
52+
function formatFontSpecification(
53+
type: "title" | "header" | "body" | "code",
54+
spec: FontSpecification,
55+
) {
5256
if (typeof spec === "string") {
5357
spec = { name: spec }
5458
}
@@ -66,9 +70,9 @@ function formatFontSpecification(type: "header" | "body" | "code", spec: FontSpe
6670
if (weights.length > 1) {
6771
const weightSpec = italic
6872
? weights
69-
.flatMap((w) => [`0,${w}`, `1,${w}`])
70-
.sort()
71-
.join(";")
73+
.flatMap((w) => [`0,${w}`, `1,${w}`])
74+
.sort()
75+
.join(";")
7276
: weights.join(";")
7377

7478
features.push(`wght@${weightSpec}`)
@@ -82,12 +86,19 @@ function formatFontSpecification(type: "header" | "body" | "code", spec: FontSpe
8286
}
8387

8488
export function googleFontHref(theme: Theme) {
85-
const { code, header, body } = theme.typography
89+
const { header, body, code } = theme.typography
8690
const headerFont = formatFontSpecification("header", header)
8791
const bodyFont = formatFontSpecification("body", body)
8892
const codeFont = formatFontSpecification("code", code)
8993

90-
return `https://fonts.googleapis.com/css2?family=${bodyFont}&family=${headerFont}&family=${codeFont}&display=swap`
94+
return `https://fonts.googleapis.com/css2?family=${headerFont}&family=${bodyFont}&family=${codeFont}&display=swap`
95+
}
96+
97+
export function googleFontSubsetHref(theme: Theme, text: string) {
98+
const title = theme.typography.title || theme.typography.header
99+
const titleFont = formatFontSpecification("title", title)
100+
101+
return `https://fonts.googleapis.com/css2?family=${titleFont}&text=${encodeURIComponent(text)}&display=swap`
91102
}
92103

93104
export interface GoogleFontFile {
@@ -96,21 +107,30 @@ export interface GoogleFontFile {
96107
extension: string
97108
}
98109

110+
const fontMimeMap: Record<string, string> = {
111+
truetype: "ttf",
112+
woff: "woff",
113+
woff2: "woff2",
114+
opentype: "otf",
115+
}
116+
99117
export async function processGoogleFonts(
100118
stylesheet: string,
101119
baseUrl: string,
102120
): Promise<{
103121
processedStylesheet: string
104122
fontFiles: GoogleFontFile[]
105123
}> {
106-
const fontSourceRegex = /url\((https:\/\/fonts.gstatic.com\/s\/[^)]+\.(woff2|ttf))\)/g
124+
const fontSourceRegex =
125+
/url\((https:\/\/fonts.gstatic.com\/.+(?:\/|(?:kit=))(.+?)[.&].+?)\)\sformat\('(\w+?)'\);/g
107126
const fontFiles: GoogleFontFile[] = []
108127
let processedStylesheet = stylesheet
109128

110129
let match
111130
while ((match = fontSourceRegex.exec(stylesheet)) !== null) {
112131
const url = match[1]
113-
const [filename, extension] = url.split("/").pop()!.split(".")
132+
const filename = match[2]
133+
const extension = fontMimeMap[match[3].toLowerCase()]
114134
const staticUrl = `https://${baseUrl}/static/fonts/${filename}.${extension}`
115135

116136
processedStylesheet = processedStylesheet.replace(url, staticUrl)
@@ -135,6 +155,7 @@ ${stylesheet.join("\n\n")}
135155
--highlight: ${theme.colors.lightMode.highlight};
136156
--textHighlight: ${theme.colors.lightMode.textHighlight};
137157
158+
--titleFont: "${getFontSpecificationName(theme.typography.title || theme.typography.header)}", ${DEFAULT_SANS_SERIF};
138159
--headerFont: "${getFontSpecificationName(theme.typography.header)}", ${DEFAULT_SANS_SERIF};
139160
--bodyFont: "${getFontSpecificationName(theme.typography.body)}", ${DEFAULT_SANS_SERIF};
140161
--codeFont: "${getFontSpecificationName(theme.typography.code)}", ${DEFAULT_MONO};
@@ -152,4 +173,4 @@ ${stylesheet.join("\n\n")}
152173
--textHighlight: ${theme.colors.darkMode.textHighlight};
153174
}
154175
`
155-
}
176+
}

0 commit comments

Comments
 (0)