diff --git a/quartz/components/pages/TagContent.tsx b/quartz/components/pages/TagContent.tsx
index eb1c1ed025315..be01ad7d41bcb 100644
--- a/quartz/components/pages/TagContent.tsx
+++ b/quartz/components/pages/TagContent.tsx
@@ -53,8 +53,14 @@ const TagContent: QuartzComponent = (props: QuartzComponentProps) => {
allFiles: pages,
};
- const contentPage = allFiles.filter((file) => file.slug === `tags/${tag}`)[0];
- const content = contentPage?.description;
+ const contentPage = allFiles.filter((file) => file.slug === `tags/${tag}`).at(0);
+
+ const root = contentPage?.htmlAst;
+ const content =
+ !root || root?.children.length === 0
+ ? contentPage?.description
+ : htmlToJsx(contentPage.filePath!, root);
+
return (
diff --git a/quartz/components/scripts/search.inline.ts b/quartz/components/scripts/search.inline.ts
index f41e5500e5c54..bb2f1a63a5317 100644
--- a/quartz/components/scripts/search.inline.ts
+++ b/quartz/components/scripts/search.inline.ts
@@ -22,6 +22,7 @@ const index = new FlexSearch.Document- ({
encode: encoder,
document: {
id: "id",
+ tag: "tags",
index: [
{
field: "title",
diff --git a/quartz/i18n/index.ts b/quartz/i18n/index.ts
index 98d330b954fe9..728e4294e7570 100644
--- a/quartz/i18n/index.ts
+++ b/quartz/i18n/index.ts
@@ -13,6 +13,8 @@ import ru from "./locales/ru-RU"
import ko from "./locales/ko-KR"
import zh from "./locales/zh-CN"
import vi from "./locales/vi-VN"
+import pt from "./locales/pt-BR"
+import hu from "./locales/hu-HU"
export const TRANSLATIONS = {
"en-US": en,
@@ -50,6 +52,8 @@ export const TRANSLATIONS = {
"ko-KR": ko,
"zh-CN": zh,
"vi-VN": vi,
+ "pt-BR": pt,
+ "hu-HU": hu,
} as const
export const defaultTranslation = "en-US";
diff --git a/quartz/i18n/locales/hu-HU.ts b/quartz/i18n/locales/hu-HU.ts
new file mode 100644
index 0000000000000..6397309b769e2
--- /dev/null
+++ b/quartz/i18n/locales/hu-HU.ts
@@ -0,0 +1,81 @@
+import { Translation } from "./definition"
+
+export default {
+ propertyDefaults: {
+ title: "Névtelen",
+ description: "Nincs leírás",
+ },
+ components: {
+ callout: {
+ note: "Jegyzet",
+ abstract: "Abstract",
+ info: "Információ",
+ todo: "Tennivaló",
+ tip: "Tipp",
+ success: "Siker",
+ question: "Kérdés",
+ warning: "Figyelmeztetés",
+ failure: "Hiba",
+ danger: "Veszély",
+ bug: "Bug",
+ example: "Példa",
+ quote: "Idézet",
+ },
+ backlinks: {
+ title: "Visszautalások",
+ noBacklinksFound: "Nincs visszautalás",
+ },
+ themeToggle: {
+ lightMode: "Világos mód",
+ darkMode: "Sötét mód",
+ },
+ explorer: {
+ title: "Fájlböngésző",
+ },
+ footer: {
+ createdWith: "Készítve ezzel:",
+ },
+ graph: {
+ title: "Grafikonnézet",
+ },
+ recentNotes: {
+ title: "Legutóbbi jegyzetek",
+ seeRemainingMore: ({ remaining }) => `${remaining} további megtekintése →`,
+ },
+ transcludes: {
+ transcludeOf: ({ targetSlug }) => `${targetSlug} áthivatkozása`,
+ linkToOriginal: "Hivatkozás az eredetire",
+ },
+ search: {
+ title: "Keresés",
+ searchBarPlaceholder: "Keress valamire",
+ },
+ tableOfContents: {
+ title: "Tartalomjegyzék",
+ },
+ contentMeta: {
+ readingTime: ({ minutes }) => `${minutes} perces olvasás`,
+ },
+ },
+ pages: {
+ rss: {
+ recentNotes: "Legutóbbi jegyzetek",
+ lastFewNotes: ({ count }) => `Legutóbbi ${count} jegyzet`,
+ },
+ error: {
+ title: "Nem található",
+ notFound: "Ez a lap vagy privát vagy nem létezik.",
+ },
+ folderContent: {
+ folder: "Mappa",
+ itemsUnderFolder: ({ count }) => `Ebben a mappában ${count} elem található.`,
+ },
+ tagContent: {
+ tag: "Címke",
+ tagIndex: "Címke index",
+ itemsUnderTag: ({ count }) => `${count} elem található ezzel a címkével.`,
+ showingFirst: ({ count }) => `Első ${count} címke megjelenítve.`,
+ totalTags: ({ count }) => `Összesen ${count} címke található.`,
+ },
+ },
+} as const satisfies Translation
diff --git a/quartz/i18n/locales/pt-BR.ts b/quartz/i18n/locales/pt-BR.ts
new file mode 100644
index 0000000000000..b59c7b47bfd5a
--- /dev/null
+++ b/quartz/i18n/locales/pt-BR.ts
@@ -0,0 +1,83 @@
+import { Translation } from "./definition"
+
+export default {
+ propertyDefaults: {
+ title: "Sem título",
+ description: "Sem descrição",
+ },
+ components: {
+ callout: {
+ note: "Nota",
+ abstract: "Abstrato",
+ info: "Info",
+ todo: "Pendência",
+ tip: "Dica",
+ success: "Sucesso",
+ question: "Pergunta",
+ warning: "Aviso",
+ failure: "Falha",
+ danger: "Perigo",
+ bug: "Bug",
+ example: "Exemplo",
+ quote: "Citação",
+ },
+ backlinks: {
+ title: "Backlinks",
+ noBacklinksFound: "Sem backlinks encontrados",
+ },
+ themeToggle: {
+ lightMode: "Tema claro",
+ darkMode: "Tema escuro",
+ },
+ explorer: {
+ title: "Explorador",
+ },
+ footer: {
+ createdWith: "Criado com",
+ },
+ graph: {
+ title: "Visão de gráfico",
+ },
+ recentNotes: {
+ title: "Notas recentes",
+ seeRemainingMore: ({ remaining }) => `Veja mais ${remaining} →`,
+ },
+ transcludes: {
+ transcludeOf: ({ targetSlug }) => `Transcrever de ${targetSlug}`,
+ linkToOriginal: "Link ao original",
+ },
+ search: {
+ title: "Pesquisar",
+ searchBarPlaceholder: "Pesquisar por algo",
+ },
+ tableOfContents: {
+ title: "Sumário",
+ },
+ contentMeta: {
+ readingTime: ({ minutes }) => `Leitura de ${minutes} min`,
+ },
+ },
+ pages: {
+ rss: {
+ recentNotes: "Notas recentes",
+ lastFewNotes: ({ count }) => `Últimas ${count} notas`,
+ },
+ error: {
+ title: "Não encontrado",
+ notFound: "Esta página é privada ou não existe.",
+ },
+ folderContent: {
+ folder: "Arquivo",
+ itemsUnderFolder: ({ count }) =>
+ count === 1 ? "1 item mneste arquivo." : `${count} items neste arquivo.`,
+ },
+ tagContent: {
+ tag: "Tag",
+ tagIndex: "Sumário de Tags",
+ itemsUnderTag: ({ count }) =>
+ count === 1 ? "1 item com esta tag." : `${count} items com esta tag.`,
+ showingFirst: ({ count }) => `Mostrando as ${count} primeiras tags.`,
+ totalTags: ({ count }) => `Encontradas ${count} tags.`,
+ },
+ },
+} as const satisfies Translation
diff --git a/quartz/plugins/transformers/ofm.ts b/quartz/plugins/transformers/ofm.ts
index 3a4615667997f..33ccff0732412 100644
--- a/quartz/plugins/transformers/ofm.ts
+++ b/quartz/plugins/transformers/ofm.ts
@@ -100,17 +100,27 @@ export const externalLinkRegex = /^https?:\/\//i;
export const arrowRegex = new RegExp(/(-{1,2}>|={1,2}>|<-{1,2}|<={1,2})/, "g");
-// (\|[^\|\[\n]*)? -> optional check if wikilink is inside a table cell
-// !? -> optional embedding
-// \[\[ -> open brace
-// ([^\[\]\|\#]+) -> one or more non-special characters ([,],|, or #) (name)
-// (#[^\[\]\|\#]+)? -> # then one or more non-special characters (heading link)
-// (\|[^\[\]\#]+)? -> \| then one or more non-special characters (alias)
-// ([^\|\n]*\|)? -> optional check if wikilink is inside a table cell
+// !? -> optional embedding
+// \[\[ -> open brace
+// ([^\[\]\|\#]+) -> one or more non-special characters ([,],|, or #) (name)
+// (#[^\[\]\|\#]+)? -> # then one or more non-special characters (heading link)
+// (\\?\|[^\[\]\#]+)? -> optional escape \ then | then one or more non-special characters (alias)
export const wikilinkRegex = new RegExp(
- /(\|[^\|\[\n]*)?!?\[\[([^\[\]\|\#\\]+)?(#+[^\[\]\|\#\\]+)?(\\?\|[^\[\]\#]+)?\]\]([^\|\n]*\|)?/,
+ /!?\[\[([^\[\]\|\#\\]+)?(#+[^\[\]\|\#\\]+)?(\\?\|[^\[\]\#]+)?\]\]/,
"g",
);
+
+// ^\|([^\n])+\|\n(\|) -> matches the header row
+// ( ?:?-{3,}:? ?\|)+ -> matches the header row separator
+// (\|([^\n])+\|\n)+ -> matches the body rows
+export const tableRegex = new RegExp(
+ /^\|([^\n])+\|\n(\|)( ?:?-{3,}:? ?\|)+\n(\|([^\n])+\|\n?)+/,
+ "gm",
+);
+
+// matches any wikilink, only used for escaping wikilinks inside tables
+export const tableWikilinkRegex = new RegExp(/(!?\[\[[^\]]*?\]\])/, "g");
+
const highlightRegex = new RegExp(/==([^=]+)==/, "g");
const commentRegex = new RegExp(/%%[\s\S]*?%%/, "g");
// from https://github.com/escwxyz/remark-obsidian-callout/blob/main/src/index.ts
@@ -172,9 +182,23 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin
src = src.toString();
}
+ // replace all wikilinks inside a table first
+ src = src.replace(tableRegex, (value) => {
+ // escape all aliases and headers in wikilinks inside a table
+ return value.replace(tableWikilinkRegex, (value, ...capture) => {
+ const [raw]: (string | undefined)[] = capture;
+ let escaped = raw ?? "";
+ escaped = escaped.replace("#", "\\#");
+ // escape pipe characters if they are not already escaped
+ escaped = escaped.replace(/((^|[^\\])(\\\\)*)\|/g, "$1\\|");
+
+ return escaped;
+ });
+ });
+
+ // replace all other wikilinks
src = src.replace(wikilinkRegex, (value, ...capture) => {
- const [rawTablePre, rawFp, rawHeader, rawAlias, rawTablePost]: (string | undefined)[] =
- capture;
+ const [rawFp, rawHeader, rawAlias]: (string | undefined)[] = capture;
const fp = rawFp ?? "";
const anchor = rawHeader?.trim().replace(/^#+/, "");
@@ -187,12 +211,6 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin
return `${embedDisplay}[${displayAlias.replace(/^\|/, "")}](${rawFp})`;
}
- // transform `[[note#^block_ref|^block_ref]]` to `[[note#^block_ref\|^block_ref]]`,
- // when the wikilink with alias is inside a table.
- if (displayAlias && displayAlias.startsWith("|") && rawTablePre && rawTablePost) {
- displayAlias = `\\${displayAlias}`;
- }
-
return `${embedDisplay}[[${fp}${displayAnchor}${displayAlias}]]`;
});
}
diff --git a/quartz/styles/base.scss b/quartz/styles/base.scss
index 26e16de4db97e..6aea8afae851d 100644
--- a/quartz/styles/base.scss
+++ b/quartz/styles/base.scss
@@ -519,3 +519,8 @@ ol.overflow {
padding-left: 1rem;
}
}
+
+.katex-display {
+ overflow-x: auto;
+ overflow-y: hidden;
+}
diff --git a/quartz/util/path.ts b/quartz/util/path.ts
index 697b49b2a2b3e..cd6e9ff358064 100644
--- a/quartz/util/path.ts
+++ b/quartz/util/path.ts
@@ -167,9 +167,12 @@ export function resolveRelative(current: FullSlug, target: FullSlug | SimpleSlug
}
export function splitAnchor(link: string): [string, string] {
- let [fp, anchor] = link.split("#", 2);
- anchor = anchor === undefined ? "" : "#" + slugAnchor(anchor);
- return [fp, anchor];
+ let [fp, anchor] = link.split("#", 2)
+ if (fp.endsWith(".pdf")) {
+ return [fp, anchor === undefined ? "" : `#${anchor}`]
+ }
+ anchor = anchor === undefined ? "" : "#" + slugAnchor(anchor)
+ return [fp, anchor]
}
export function slugTag(tag: string) {