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) {