Quartz è un tool che genera siti completi a partire da note scritte in Markdown. Per scrivere queste note in Markdown, uso Obsidian.

1 - Installazione e troubleshooting

Seguire la guida per l’installazione indicata sul sito di Quartz.

Se durante l’installazione, dopo aver eseguito il comando npm i, esce un errore del genere:

added 526 packages, and audited 528 packages in 9s
 
173 packages are looking for funding
  run npm fund for details
 
3 vulnerabilities (2 moderate, 1 high)
 
To address all issues, run:
  npm audit fix
 
Run npm audit for details.

Allora eseguire il comando npm audit fix per risolvere.

Se durante il clone vi esce il seguente messaggio:

error: RPC failed; curl 92 HTTP/2 stream 5 was not closed cleanly: CANCEL (err 8)
error: 40 bytes of body are still expected
fetch-pack: unexpected disconnect while reading sideband packet
fatal: early EOF
fatal: fetch-pack: invalid index-pack output

Allora significa che c’è stato un problema di connessione, quindi rieseguire il clone.

2 - Configurazione

Ecco quello che ho modificato nei file di Quartz per ottenere la configurazione che adotta per generare questo sito.

2.1 - Configurazione generale

Nel file quartz.config.ts ho modificato così:

  • pageTitle: "🪴 Giardino Digitale di Rexus752": titolo che esce all’inizio di ogni pagina.
  • locale: "it-IT": per impostare la lingua in italiano.
  • baseUrl: "rexus752.pages.dev": URL del sito.

2.2 - Layout del sito

Questo è il layout che uso nel mio sito, impostabile dal file quartz.layout.ts.

import { PageLayout, SharedLayout } from "./quartz/cfg"
import * as Component from "./quartz/components"
 
// components shared across all pages
export const sharedPageComponents: SharedLayout = {
	head: Component.Head(),
	header: [],
	afterBody: [
		Component.Comments({
			provider: 'giscus',
			options: {
				// from data-repo
				repo: 'Rexus752/digital-garden',
				// from data-repo-id
				repoId: 'R_kgDONHp66Q',
				// from data-category
				category: 'Announcements',
				// from data-category-id
				categoryId: 'DIC_kwDONHp66c4Cjzbq',
			}
		}),
	],
	footer: Component.Footer({
		links: {
			"GitHub Repository": "https://github.com/Rexus752/digital-garden",
		},
	}),
}
 
// components for pages that display a single page (e.g. a single note)
export const defaultContentPageLayout: PageLayout = {
	beforeBody: [
		// Component.Breadcrumbs(),
		Component.MobileOnly(Component.TableOfContents()),
		Component.ArticleTitle(),
		Component.ContentMeta(),
		Component.TagList(),
	],
	left: [
		Component.PageTitle(),
		Component.Search(),
		Component.Graph(),
		// Component.Darkmode(),
	],
	right: [
		// Component.DesktopOnly(Component.Explorer()),
		Component.DesktopOnly(Component.TableOfContents()),
	],
}
 
// components for pages that display lists of pages	(e.g. tags or folders)
export const defaultListPageLayout: PageLayout = {
	beforeBody: [
		// Component.Breadcrumbs(),
		Component.ArticleTitle(),
		Component.ContentMeta(),
	],
	left: [
		Component.PageTitle(),
		Component.MobileOnly(Component.Spacer()),
		Component.Search(),
		// Component.Darkmode(),
	],
	right: [
		// Component.DesktopOnly(Component.Explorer()),
		Component.Graph(),
	],
}
 

2.3 - Icona personalizzata

Nella cartella quartz/static ho messo la mia icon.png per dare l’icona al sito. L’icona l’ho creata attraverso questo generatore sul sito ufficiale di Obsidian che ti permette di personalizzare la nuova icona di Obsidian adottata nel 2023 con i propri colori (e io ho usato l’azzurro e il rosa perché ricordano la mia classica propic che uso ovunque).

2.4 - Modalità scura di default

Impostare la modalità scura di default sul sito è un bel casino, ci ho messo un bel po’ per capire come diamine farlo, ma alla fine ho scelto l’opzione più stupida e più diretta per realizzarlo: nel file quartz.config.ts ho scambiato di posto le parole lightMode e darkMode.

colors: {
	darkMode: {
		light: "#faf8f8",
		lightgray: "#e5e5e5",
		gray: "#b8b8b8",
		darkgray: "#4e4e4e",
		dark: "#2b2b2b",
		secondary: "#284b63",
		tertiary: "#84a59d",
		highlight: "rgba(143, 159, 169, 0.15)",
		textHighlight: "#fff23688",
	},
	lightMode: {
		light: "#161618",
		lightgray: "#393639",
		gray: "#646464",
		darkgray: "#d4d4d4",
		dark: "#ebebec",
		secondary: "#7b97aa",
		tertiary: "#84a59d",
		highlight: "rgba(143, 159, 169, 0.15)",
		textHighlight: "#b3aa0288",
	},
},

Stessa cosa ho fatto per quanto riguarda il syntax highlighting (sempre in quartz.config.ts), al quale ho applicato i colori scuri semplicemente scambiando i valori github-light e github-dark:

Plugin.SyntaxHighlighting({
	theme: {
		light: "github-dark",
		dark: "github-light",
	},
	keepBackground: false,
}),

Per quanto riguarda invece i diagrammi Mermaid, questi sono inclusi in tutto ciò che riguarda la compatibilità di Quartz con Obsidian e, di conseguenza, sono gestiti dal plugin ObsidianFlavoredMarkdown. Per invertire i colori anche nei diagrammi, nel file quartz/plugins/transformers/ofm.ts, approssimativamente alla riga 695, bisogna scambiare i valori 'dark' e 'default':

script: `
let mermaidImport = undefined
document.addEventListener('nav', async () => {
if (document.querySelector("code.mermaid")) {
  mermaidImport ||= await import('https://cdnjs.cloudflare.com/ajax/libs/mermaid/10.7.0/mermaid.esm.min.mjs')
  const mermaid = mermaidImport.default
  const darkMode = document.documentElement.getAttribute('saved-theme') === 'dark'
  mermaid.initialize({
	startOnLoad: false,
	securityLevel: 'loose',
	theme: darkMode ? 'default' : 'dark'
  })
 
  await mermaid.run({
	querySelector: '.mermaid'
  })
}
});
`,

2.5 - SCSS personalizzato

Nel file quartz/styles/customs.scss ci vanno le configurazioni personalizzate per lo stile.

2.5.1 - Tabelle

Il padding delle tabelle l’ho modificato in modo da renderle un po’ più “compatte” senza lasciar passare l’intera Autostrada del Sole tra il contenuto della cella e il bordo.

.table-container {
	& > table {
		margin: 0rem;
		padding: 0rem;
		& > * {
			line-height: 1.2rem;
		}
	}
}
 
th {
	text-align: center;
	border: 1px solid var(--gray);
	background-color: var(--lightgray);
}
 
td {
	border: 1px solid var(--lightgray);
}

Inoltre, per alternare i colori delle righe (in modo da distinguerle più facilmente), ho aggiunto questo:

tbody tr:nth-child(2n) {
	background-color: #2F2F2F7F;
}

Nota: quel 7F finale alla fine del codice del colore serve per rendere trasparente la riga della tabella, in modo che nei callout colorati faccia trasparire il colore dello sfondo.

2.5.2 - Componenti aperti nelle barri laterali

Dal momento che alcune pagine hanno degli indici (table of contents) nelle barre laterali molto lunghi, con il layout standard di Quartz non è facile scorrere lungo la lista per trovare il paragrafo desiderato all’interno dello spazio ristretto nella barra laterale:

Proprio per questo, ho deciso di rendere gli indici (e di conseguenza anche tutti gli altri componenti all’interno delle barre laterali, come l’explorer) “aperti”, in modo che non ci sia bisogno di scrollare all’interno del componente, ma che basti scrollare lungo l’intera pagina. Il codice da inserire nel quartz/styles/customs.scss è il seguente:

.page {
	& > #quartz-body {
		& .sidebar {
			min-height: 100vh;
			height: auto !important;
		}
	}
}

2.6 - Padding della pagina

Nel file quartz/styles/variables.scss ho modificato le seguenti righe per evitare di avere spazio inutilmente occupato all’inizio della pagina e ai lati.

$sidePanelWidth: 300px; // Initial value: 380px
$topSpacing: 2rem; // Initial value: 6rem

2.7 - Traduzioni in italiano

Nel file delle traduzioni in italiano (quartz/i18n/locales/it-IT.ts) ho modificato le seguenti traduzioni.

graph: {
  title: "Vista grafo",
},
tableOfContents: {
  title: "Indice",
},
contentMeta: {
  readingTime: ({ minutes }) => `${minutes} minuti di lettura`,
},

2.8 - Callout personalizzati

All’interno del mio Giardino Digitale, uso i seguenti callout personalizzati, dichiarati nel file quartz/styles/custom.scss. Sul sito di Quartz viene spiegato come aggiungerne di nuovi.

Io, per aggiungere nuovi callout, uso questo metodo:

  • Cerco una possibile icona su FontAwesome.
  • Copio il codice SVG.
  • Lo converto in URL tramite questo tool.
  • Lo aggiungo nel file custom.scss con il seguente formato:
    .callout {
    	&[data-callout="<name>"] {
    		--color: #<color>;
    	    --border: #<border color>;
    		--bg: #<background color>;
    		--callout-icon: url("data:image/svg+xml; utf8, <custom formatted SVG icon code>");
    	}
    }

2.8.1 - Lista dei callout che uso

Ecco una lista dei callout che uso, ognuno dei quali ha al proprio interno il codice SCSS per impostarlo (clicca sulla freccetta affianco al titolo del callout per espanderlo).

2.8.1.1 - Generici

2.8.1.2 - Per la matematica

2.8.1.2 - Per l’informatica

3 - Problemi di Quartz

Ecco una lista di problemi che ho trovato usando Quartz e come li ho risolti. Per molti di questi problemi non ho ancora trovato una soluzione e, non avendo idea di come risolverli, credo che semplicemente aspetterò che il creatore di Quartz (Jacky Zhao) lo faccia.

Descrizione del problema: se ho un link del tipo:

[processi I/O-bound](Processi.md#4.1%20-%20Processo%20I/O-bound)

Quel / nel displayed name del link crede sia tipo un path quindi compare solo come link O-bound.

Soluzione: non l’ho ancora risolto (lol), infatti nella pagina Processi si trovano dei link O-bound.

3.2 - Table Of Contents non renderizza correttamente il LaTeX e l’HTML

Descrizione del problema: il Table Of Contents (l’indice al lato) renderizza i pezzetti di codice inline come testo normale. Fin qui non ci sarebbe nessun problema, se non fosse che non renderizza neanche il LaTeX inline. Anche i tag HTML che usavo per cambiare colore al font (es. <span style="color:#FF7FFF; background:#00000000">Prova</span>) non me li renderizzava ma me li prendeva come testo normale.

Soluzione: non l’ho ancora risolto, però ho intenzione di provare a integrare una sorta di “renderer” in Quartz (però c’è da studiarsi come funziona il parsing dei dati per creare il Table Of Contents e se è effettivamente fattibile o meno).

3.3 - Table Of Contents mezza colonna

Descrizione del problema: se Component.TableOfContents() viene specificato come DesktopOnly (quindi con Component.DesktopOnly(Component.TableOfContents())), occupa solo mezza colonna anziché l’intero resto della colonna laterale in cui viene inserito.

Soluzione: non l’ho ancora risolto, infatti occupa ancora solo mezza colonna laterale.

3.4 - Table Of Contents fisso se non DesktopOnly

Descrizione del problema: se Component.TableOfContents() non viene specificato come DesktopOnly (quindi con Component.DesktopOnly(Component.TableOfContents())), non si può scorrere.

Soluzione: non l’ho ancora risolto.

Descrizione del problema: se in una pagina clicco su un link che mi porta a un heading nella stessa pagina, a volte non succede nulla oppure porta a un altro heading.

Soluzione: cliccare sui link aprendoli in un’altra tab (col Middle Click) anziché nella stessa tab (col Left Click). È una soluzione alternativa non ottimale, ma non ho idea di come si possa sistemare.

3.6 - File e cartelle con stesso nome nella stessa cartella

Descrizione del problema: Quartz si rincoglionisce quando ci sono file e cartelle con lo stesso nome nella stessa cartella, in particolare:

  • Nell’explorer compare solo la pagina, ma non la cartella.
  • Sminchia completamente gli hyperlink nelle breadcrumb.

Soluzione: è una soluzione alternativa (ma almeno funziona), ossia mettere 📁 all’inizio del nome della cartella, così Quartz riesce a distinguerli non avendo entrambi lo stesso nome.

3.7 - Titoli dei callout non colorano il LaTeX

Descrizione del problema: se ho un callout di questo tipo, i blocchi di LaTeX inline nel titolo del callout non vengono colorati ma rimangono bianchi:

Esempio: l'identità di Eulero

L’identità di Eulero nel titolo del callout dovrebbe essere colorata in blu come il resto del titolo.

Soluzione: è una soluzione alternativa (ma almeno funziona), ossia mettere \color{<codice colore>} nel blocco inline di LaTeX.

Esempio: l'identità di Eulero

Ora l’identità di Eulero nel titolo del callout è colorata in blu! Il codice LaTeX del blocco inline è $\color{#7F7FFF} e^{i\pi} + 1 = 0$.

3.8 - Block reference con le maiuscole non vengono riconosciute

Descrizione del problema: se ho una block reference (ossia quei link del tipo #^nome-blocco) con delle lettere maiuscole all’interno, Quartz non me le riconosce. Infatti, nel caso di un link a una block reference del tipo nome_pagina.md#^Nome-blocco, Quartz prova a reindirizzarmi al link nome_pagina.md#^nome-blocco e, essendo gli URL case-sentitive, i due URL non corrispondono.

Soluzione: eliminare ogni lettera maiuscola dalle block reference.

3.9 - Block reference punta alla fine del callout e non all’intero callout

Descrizione del problema: se ho una block reference che identifica un callout, Quartz me la fa “puntare” all’ultimo blocco all’interno del callout e non all’intero callout, facendo così risultare la preview e il reindirizzamento al blocco non all’inizio del callout ma alla sua fine. Per esempio, se ho un callout con un unico blocco:

Esempio: callout con un unico blocco

Questo callout ha un unico blocco e ha una block reference che si chiama ^callout-unico-blocco.

Il link al callout link ([link](Quartz.md#^callout-unico-blocco)) punterà solo al testo all’interno del callout, essendo questo secondo Quartz l’ultimo blocco puntato dalla block reference, e non all’intero callout. Ugualmente, un callout con un elenco puntato:

Esempio: callout con un elenco puntato

  • Questo callout ha un elenco puntato.
  • Ha una block reference che si chiama ^callout-elenco-puntato.

Il link al callout link ([link](Quartz.md#^callout-elenco-puntato)) punterà all’ultimo punto all’interno del callout, essendo questo secondo Quartz l’ultimo blocco puntato dalla block reference, e non all’intero callout.

Soluzione: non ho ancora trovato una soluzione, gli utenti del sito dovranno scrollare manualmente un pochino verso l’alto ogni volta che vengono reindirizzati al callout.

4 - TODO

Lista delle cose che ho in mente di fare prima o poi per migliorare questo Giardino Digitale:

  1. Risolvere tutti i problemi di Quartz, possibilmente anche quelli risolti momentaneamente con soluzioni alternative.
  2. Cambiare il carattere monospaziato usato per il codice (quando è inline è inguardabile per me).
  3. Diminuire la dimensione di tutti i caratteri nel Giardino e rendere il LaTeX della stessa dimensione del carattere normale.
  4. Aggiungere la possibilità di zoommare sulle immagini cliccandoci.
  5. Aggiungere la possibilità di poter ridimensionare le immagini direttamente tramite sintassi Markdown.
  6. Una finestre pop-up che si attiva quando si fa hover su un link deve poterne creare un’altra e così via.
  7. Usare un carattere ad alta leggibilità (amici dislessici io non mi dimentico di voi).
  8. Diminuire il padding all’inizio di ogni callout.
  9. Per la visualizzazione da mobile: aggiungere un pulsante fluttuante per vedere il Table Of Contents.
  10. Per la visualizzazione da desktop: aggiungere un Table Of Contents fluttuante sul lato (stile Notion).
  11. Aggiungere una funzionalità per aprire una nota casuale nel Giardino Digitale.
  12. Cercare di integrare il plugin Iconize aggiungendo le icone alle pagine e le icone inline.
  13. Le tabelle non devono essere scrollabili in larghezza, ma devono essere fixed con larghezza pari alla larghezza del body.
  14. Aggiungere una traduzione in italiano di “Footnotes” e tradurre in italiano la roba di Giscus.