diff --git a/docs/advanced/making plugins.md b/docs/advanced/making plugins.md index 0ba29680c..9925d16c9 100644 --- a/docs/advanced/making plugins.md +++ b/docs/advanced/making plugins.md @@ -27,7 +27,7 @@ The following sections will go into detail for what methods can be implemented f - `cfg`: The full Quartz [[configuration]] - `allSlugs`: a list of all the valid content slugs (see [[paths]] for more information on what a `ServerSlug` is) - `StaticResources` is defined in `quartz/resources.tsx`. It consists of - - `css`: a list of URLs for stylesheets that should be loaded + - `css`: a list of CSS style definitions that should be loaded. A CSS style is described with the `CSSResource` type which is also defined in `quartz/resources.tsx`. It accepts either a source URL or the inline content of the stylesheet. - `js`: a list of scripts that should be loaded. A script is described with the `JSResource` type which is also defined in `quartz/resources.tsx`. It allows you to define a load time (either before or after the DOM has been loaded), whether it should be a module, and either the source URL or the inline content of the script. ## Transformers @@ -85,8 +85,10 @@ export const Latex: QuartzTransformerPlugin = (opts?: Options) => { if (engine === "katex") { return { css: [ - // base css - "https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.9/katex.min.css", + { + // base css + content: "https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.9/katex.min.css", + }, ], js: [ { diff --git a/package-lock.json b/package-lock.json index 18349a5eb..7a543fd1c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,14 +33,14 @@ "mdast-util-to-hast": "^13.2.0", "mdast-util-to-string": "^4.0.0", "micromorph": "^0.4.5", - "pixi.js": "^8.5.1", + "pixi.js": "^8.5.2", "preact": "^10.24.3", "preact-render-to-string": "^6.5.11", "pretty-bytes": "^6.1.1", "pretty-time": "^1.1.0", "reading-time": "^1.5.0", "rehype-autolink-headings": "^7.1.0", - "rehype-citation": "^2.2.0", + "rehype-citation": "^2.2.1", "rehype-katex": "^7.0.1", "rehype-mathjax": "^6.0.0", "rehype-pretty-code": "^0.14.0", @@ -57,7 +57,7 @@ "rfdc": "^1.4.1", "rimraf": "^6.0.1", "serve-handler": "^6.1.6", - "shiki": "^1.22.0", + "shiki": "^1.22.2", "source-map-support": "^0.5.21", "to-vfile": "^8.0.0", "toml": "^3.0.0", @@ -76,14 +76,14 @@ "@types/d3": "^7.4.3", "@types/hast": "^3.0.4", "@types/js-yaml": "^4.0.9", - "@types/node": "^22.7.7", + "@types/node": "^22.8.1", "@types/pretty-time": "^1.1.5", "@types/source-map-support": "^0.5.10", "@types/ws": "^8.5.12", "@types/yargs": "^17.0.33", "esbuild": "^0.24.0", "prettier": "^3.3.3", - "tsx": "^4.19.1", + "tsx": "^4.19.2", "typescript": "^5.6.3" }, "engines": { @@ -898,41 +898,41 @@ } }, "node_modules/@shikijs/core": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.22.0.tgz", - "integrity": "sha512-S8sMe4q71TJAW+qG93s5VaiihujRK6rqDFqBnxqvga/3LvqHEnxqBIOPkt//IdXVtHkQWKu4nOQNk0uBGicU7Q==", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.22.2.tgz", + "integrity": "sha512-bvIQcd8BEeR1yFvOYv6HDiyta2FFVePbzeowf5pPS1avczrPK+cjmaxxh0nx5QzbON7+Sv0sQfQVciO7bN72sg==", "dependencies": { - "@shikijs/engine-javascript": "1.22.0", - "@shikijs/engine-oniguruma": "1.22.0", - "@shikijs/types": "1.22.0", + "@shikijs/engine-javascript": "1.22.2", + "@shikijs/engine-oniguruma": "1.22.2", + "@shikijs/types": "1.22.2", "@shikijs/vscode-textmate": "^9.3.0", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.3" } }, "node_modules/@shikijs/engine-javascript": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.22.0.tgz", - "integrity": "sha512-AeEtF4Gcck2dwBqCFUKYfsCq0s+eEbCEbkUuFou53NZ0sTGnJnJ/05KHQFZxpii5HMXbocV9URYVowOP2wH5kw==", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.22.2.tgz", + "integrity": "sha512-iOvql09ql6m+3d1vtvP8fLCVCK7BQD1pJFmHIECsujB0V32BJ0Ab6hxk1ewVSMFA58FI0pR2Had9BKZdyQrxTw==", "dependencies": { - "@shikijs/types": "1.22.0", + "@shikijs/types": "1.22.2", "@shikijs/vscode-textmate": "^9.3.0", "oniguruma-to-js": "0.4.3" } }, "node_modules/@shikijs/engine-oniguruma": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.22.0.tgz", - "integrity": "sha512-5iBVjhu/DYs1HB0BKsRRFipRrD7rqjxlWTj4F2Pf+nQSPqc3kcyqFFeZXnBMzDf0HdqaFVvhDRAGiYNvyLP+Mw==", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.22.2.tgz", + "integrity": "sha512-GIZPAGzQOy56mGvWMoZRPggn0dTlBf1gutV5TdceLCZlFNqWmuc7u+CzD0Gd9vQUTgLbrt0KLzz6FNprqYAxlA==", "dependencies": { - "@shikijs/types": "1.22.0", + "@shikijs/types": "1.22.2", "@shikijs/vscode-textmate": "^9.3.0" } }, "node_modules/@shikijs/types": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.22.0.tgz", - "integrity": "sha512-Fw/Nr7FGFhlQqHfxzZY8Cwtwk5E9nKDUgeLjZgt3UuhcM3yJR9xj3ZGNravZZok8XmEZMiYkSMTPlPkULB8nww==", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.22.2.tgz", + "integrity": "sha512-NCWDa6LGZqTuzjsGfXOBWfjS/fDIbDdmVDug+7ykVe1IKT4c1gakrvlfFYp5NhAXH/lyqLM8wsAPo5wNy73Feg==", "dependencies": { "@shikijs/vscode-textmate": "^9.3.0", "@types/hast": "^3.0.4" @@ -1307,12 +1307,12 @@ } }, "node_modules/@types/node": { - "version": "22.7.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.7.tgz", - "integrity": "sha512-SRxCrrg9CL/y54aiMCG3edPKdprgMVGDXjA3gB8UmmBW5TcXzRUYAh8EWzTnSJFAd1rgImPELza+A3bJ+qxz8Q==", + "version": "22.8.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.8.1.tgz", + "integrity": "sha512-k6Gi8Yyo8EtrNtkHXutUu2corfDf9su95VYVP10aGYMMROM6SAItZi0w1XszA6RtWTHSVp5OeFof37w0IEqCQg==", "dev": true, "dependencies": { - "undici-types": "~6.19.2" + "undici-types": "~6.19.8" } }, "node_modules/@types/pretty-time": { @@ -4878,9 +4878,9 @@ } }, "node_modules/pixi.js": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/pixi.js/-/pixi.js-8.5.1.tgz", - "integrity": "sha512-yYj8tWehUfH7or/34gf17XyZGnyjiG8toMH8oy9gP+4GjLK+/WjFLlRqaP0AECB8XGF8AJxgkS5y2aMDHqx11A==", + "version": "8.5.2", + "resolved": "https://registry.npmjs.org/pixi.js/-/pixi.js-8.5.2.tgz", + "integrity": "sha512-TOt9g8ifOj4R9DN9ST1M8t2nvnuhr5oWL5YW9ywFLbnOVgFMDcEz+Xek5Mo8Xr64D+QU3qre3IFgreBlsHxTNw==", "dependencies": { "@pixi/colord": "^2.9.6", "@types/css-font-loading-module": "^0.0.12", @@ -5030,9 +5030,9 @@ } }, "node_modules/rehype-citation": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/rehype-citation/-/rehype-citation-2.2.0.tgz", - "integrity": "sha512-alEc/TxDqyALcHt9/MXUBjrCLl+It3q3gqkX0gGv6k3nyJm7CUAOOYxuywWyu6Cljf8DZFCJ9u+oVV/nRgRyYQ==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/rehype-citation/-/rehype-citation-2.2.1.tgz", + "integrity": "sha512-8Ybq4W0/FeuXSwTrwpDbsZ9v0X0ZeKxDKyA/9s1EI2GMZLgaowPEkFOyXhOjv7Ud2ntK86AWkove38G4U0dRuQ==", "dependencies": { "@citation-js/core": "^0.7.14", "@citation-js/date": "^0.5.1", @@ -5992,14 +5992,14 @@ } }, "node_modules/shiki": { - "version": "1.22.0", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.22.0.tgz", - "integrity": "sha512-/t5LlhNs+UOKQCYBtl5ZsH/Vclz73GIqT2yQsCBygr8L/ppTdmpL4w3kPLoZJbMKVWtoG77Ue1feOjZfDxvMkw==", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.22.2.tgz", + "integrity": "sha512-3IZau0NdGKXhH2bBlUk4w1IHNxPh6A5B2sUpyY+8utLu2j/h1QpFkAaUA1bAMxOWWGtTWcAh531vnS4NJKS/lA==", "dependencies": { - "@shikijs/core": "1.22.0", - "@shikijs/engine-javascript": "1.22.0", - "@shikijs/engine-oniguruma": "1.22.0", - "@shikijs/types": "1.22.0", + "@shikijs/core": "1.22.2", + "@shikijs/engine-javascript": "1.22.2", + "@shikijs/engine-oniguruma": "1.22.2", + "@shikijs/types": "1.22.2", "@shikijs/vscode-textmate": "^9.3.0", "@types/hast": "^3.0.4" } @@ -6344,9 +6344,9 @@ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" }, "node_modules/tsx": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.1.tgz", - "integrity": "sha512-0flMz1lh74BR4wOvBjuh9olbnwqCPc35OOlfyzHba0Dc+QNUeWX/Gq2YTbnwcWPO3BMd8fkzRVrHcsR+a7z7rA==", + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.2.tgz", + "integrity": "sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g==", "dev": true, "dependencies": { "esbuild": "~0.23.0", diff --git a/package.json b/package.json index 9423e09db..97cde0464 100644 --- a/package.json +++ b/package.json @@ -59,14 +59,14 @@ "mdast-util-to-hast": "^13.2.0", "mdast-util-to-string": "^4.0.0", "micromorph": "^0.4.5", - "pixi.js": "^8.5.1", + "pixi.js": "^8.5.2", "preact": "^10.24.3", "preact-render-to-string": "^6.5.11", "pretty-bytes": "^6.1.1", "pretty-time": "^1.1.0", "reading-time": "^1.5.0", "rehype-autolink-headings": "^7.1.0", - "rehype-citation": "^2.2.0", + "rehype-citation": "^2.2.1", "rehype-katex": "^7.0.1", "rehype-mathjax": "^6.0.0", "rehype-pretty-code": "^0.14.0", @@ -83,7 +83,7 @@ "rfdc": "^1.4.1", "rimraf": "^6.0.1", "serve-handler": "^6.1.6", - "shiki": "^1.22.0", + "shiki": "^1.22.2", "source-map-support": "^0.5.21", "to-vfile": "^8.0.0", "toml": "^3.0.0", @@ -99,14 +99,14 @@ "@types/d3": "^7.4.3", "@types/hast": "^3.0.4", "@types/js-yaml": "^4.0.9", - "@types/node": "^22.7.7", + "@types/node": "^22.8.1", "@types/pretty-time": "^1.1.5", "@types/source-map-support": "^0.5.10", "@types/ws": "^8.5.12", "@types/yargs": "^17.0.33", "esbuild": "^0.24.0", "prettier": "^3.3.3", - "tsx": "^4.19.1", + "tsx": "^4.19.2", "typescript": "^5.6.3" } } diff --git a/quartz/components/Head.tsx b/quartz/components/Head.tsx index 90e338730..cf79434fa 100644 --- a/quartz/components/Head.tsx +++ b/quartz/components/Head.tsx @@ -1,6 +1,6 @@ import { i18n } from "../i18n" import { FullSlug, joinSegments, pathToRoot } from "../util/path" -import { JSResourceToScriptElement } from "../util/resources" +import { CSSResourceToStyleElement, JSResourceToScriptElement } from "../util/resources" import { googleFontHref } from "../util/theme" import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } from "./types" @@ -40,9 +40,7 @@ export default (() => { - {css.map((href) => ( - - ))} + {css.map((resource) => CSSResourceToStyleElement(resource, true))} {js .filter((resource) => resource.loadTime === "beforeDOMReady") .map((res) => JSResourceToScriptElement(res, true))} diff --git a/quartz/components/pages/FolderContent.tsx b/quartz/components/pages/FolderContent.tsx index dc216cde7..7a49d494f 100644 --- a/quartz/components/pages/FolderContent.tsx +++ b/quartz/components/pages/FolderContent.tsx @@ -2,22 +2,25 @@ import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } fro import path from "path" import style from "../styles/listPage.scss" -import { PageList, SortFn } from "../PageList" -import { stripSlashes, simplifySlug } from "../../util/path" +import { byDateAndAlphabetical, PageList, SortFn } from "../PageList" +import { stripSlashes, simplifySlug, joinSegments, FullSlug } from "../../util/path" import { Root } from "hast" import { htmlToJsx } from "../../util/jsx" import { i18n } from "../../i18n" +import { QuartzPluginData } from "../../plugins/vfile" interface FolderContentOptions { /** * Whether to display number of folders */ showFolderCount: boolean + showSubfolders: boolean sort?: SortFn } const defaultOptions: FolderContentOptions = { showFolderCount: true, + showSubfolders: true, } export default ((opts?: Partial) => { @@ -26,14 +29,47 @@ export default ((opts?: Partial) => { const FolderContent: QuartzComponent = (props: QuartzComponentProps) => { const { tree, fileData, allFiles, cfg } = props const folderSlug = stripSlashes(simplifySlug(fileData.slug!)) - const allPagesInFolder = allFiles.filter((file) => { + const folderParts = folderSlug.split(path.posix.sep) + + const allPagesInFolder: QuartzPluginData[] = [] + const allPagesInSubfolders: Map = new Map() + + allFiles.forEach((file) => { const fileSlug = stripSlashes(simplifySlug(file.slug!)) const prefixed = fileSlug.startsWith(folderSlug) && fileSlug !== folderSlug - const folderParts = folderSlug.split(path.posix.sep) const fileParts = fileSlug.split(path.posix.sep) const isDirectChild = fileParts.length === folderParts.length + 1 - return prefixed && isDirectChild + + if (!prefixed) { + return + } + + if (isDirectChild) { + allPagesInFolder.push(file) + } else if (options.showSubfolders) { + const subfolderSlug = joinSegments( + ...fileParts.slice(0, folderParts.length + 1), + ) as FullSlug + const pagesInFolder = allPagesInSubfolders.get(subfolderSlug) || [] + allPagesInSubfolders.set(subfolderSlug, [...pagesInFolder, file]) + } }) + + allPagesInSubfolders.forEach((files, subfolderSlug) => { + const hasIndex = allPagesInFolder.some( + (file) => subfolderSlug === stripSlashes(simplifySlug(file.slug!)), + ) + if (!hasIndex) { + const subfolderDates = files.sort(byDateAndAlphabetical(cfg))[0].dates + const subfolderTitle = subfolderSlug.split(path.posix.sep).at(-1)! + allPagesInFolder.push({ + slug: subfolderSlug, + dates: subfolderDates, + frontmatter: { title: subfolderTitle, tags: ["folder"] }, + }) + } + }) + const cssClasses: string[] = fileData.frontmatter?.cssclasses ?? [] const classes = ["popover-hint", ...cssClasses].join(" ") const listProps = { diff --git a/quartz/components/renderPage.tsx b/quartz/components/renderPage.tsx index f2dcceaa5..9c530967b 100644 --- a/quartz/components/renderPage.tsx +++ b/quartz/components/renderPage.tsx @@ -29,7 +29,12 @@ export function pageResources( const contentIndexScript = `const fetchData = fetch("${contentIndexPath}").then(data => data.json())` return { - css: [joinSegments(baseDir, "index.css"), ...staticResources.css], + css: [ + { + content: joinSegments(baseDir, "index.css"), + }, + ...staticResources.css, + ], js: [ { src: joinSegments(baseDir, "prescript.js"), diff --git a/quartz/i18n/index.ts b/quartz/i18n/index.ts index 2fba70e16..f328ada8d 100644 --- a/quartz/i18n/index.ts +++ b/quartz/i18n/index.ts @@ -20,6 +20,7 @@ import hu from "./locales/hu-HU" import fa from "./locales/fa-IR" import pl from "./locales/pl-PL" import cs from "./locales/cs-CZ" +import tr from "./locales/tr-TR" export const TRANSLATIONS = { "en-US": enUs, @@ -64,6 +65,7 @@ export const TRANSLATIONS = { "fa-IR": fa, "pl-PL": pl, "cs-CZ": cs, + "tr-TR": tr, } as const export const defaultTranslation = "en-US" diff --git a/quartz/i18n/locales/tr-TR.ts b/quartz/i18n/locales/tr-TR.ts new file mode 100644 index 000000000..a3805d1a9 --- /dev/null +++ b/quartz/i18n/locales/tr-TR.ts @@ -0,0 +1,84 @@ +import { Translation } from "./definition" + +export default { + propertyDefaults: { + title: "İsimsiz", + description: "Herhangi bir açıklama eklenmedi", + }, + components: { + callout: { + note: "Not", + abstract: "Özet", + info: "Bilgi", + todo: "Yapılacaklar", + tip: "İpucu", + success: "Başarılı", + question: "Soru", + warning: "Uyarı", + failure: "Başarısız", + danger: "Tehlike", + bug: "Hata", + example: "Örnek", + quote: "Alıntı", + }, + backlinks: { + title: "Backlinkler", + noBacklinksFound: "Backlink bulunamadı", + }, + themeToggle: { + lightMode: "Açık mod", + darkMode: "Koyu mod", + }, + explorer: { + title: "Gezgin", + }, + footer: { + createdWith: "Şununla oluşturuldu", + }, + graph: { + title: "Grafik Görünümü", + }, + recentNotes: { + title: "Son Notlar", + seeRemainingMore: ({ remaining }) => `${remaining} tane daha gör →`, + }, + transcludes: { + transcludeOf: ({ targetSlug }) => `${targetSlug} sayfasından alıntı`, + linkToOriginal: "Orijinal bağlantı", + }, + search: { + title: "Arama", + searchBarPlaceholder: "Bir şey arayın", + }, + tableOfContents: { + title: "İçindekiler", + }, + contentMeta: { + readingTime: ({ minutes }) => `${minutes} dakika okuma süresi`, + }, + }, + pages: { + rss: { + recentNotes: "Son notlar", + lastFewNotes: ({ count }) => `Son ${count} not`, + }, + error: { + title: "Bulunamadı", + notFound: "Bu sayfa ya özel ya da mevcut değil.", + home: "Anasayfaya geri dön", + }, + folderContent: { + folder: "Klasör", + itemsUnderFolder: ({ count }) => + count === 1 ? "Bu klasör altında 1 öğe." : `Bu klasör altındaki ${count} öğe.`, + }, + tagContent: { + tag: "Etiket", + tagIndex: "Etiket Sırası", + itemsUnderTag: ({ count }) => + count === 1 ? "Bu etikete sahip 1 öğe." : `Bu etiket altındaki ${count} öğe.`, + showingFirst: ({ count }) => `İlk ${count} etiket gösteriliyor.`, + totalTags: ({ count }) => `Toplam ${count} adet etiket bulundu.`, + }, + }, +} as const satisfies Translation diff --git a/quartz/plugins/emitters/folderPage.tsx b/quartz/plugins/emitters/folderPage.tsx index 7eebb21c7..b6d860272 100644 --- a/quartz/plugins/emitters/folderPage.tsx +++ b/quartz/plugins/emitters/folderPage.tsx @@ -76,12 +76,11 @@ export const FolderPage: QuartzEmitterPlugin> = (user const folders: Set = new Set( allFiles.flatMap((data) => { - const slug = data.slug - const folderName = path.dirname(slug ?? "") as SimpleSlug - if (slug && folderName !== "." && folderName !== "tags") { - return [folderName] - } - return [] + return data.slug + ? _getFolders(data.slug).filter( + (folderName) => folderName !== "." && folderName !== "tags", + ) + : [] }), ) @@ -133,3 +132,14 @@ export const FolderPage: QuartzEmitterPlugin> = (user }, } } + +function _getFolders(slug: FullSlug): SimpleSlug[] { + var folderName = path.dirname(slug ?? "") as SimpleSlug + const parentFolderNames = [folderName] + + while (folderName !== ".") { + folderName = path.dirname(folderName ?? "") as SimpleSlug + parentFolderNames.push(folderName) + } + return parentFolderNames +} diff --git a/quartz/plugins/transformers/latex.ts b/quartz/plugins/transformers/latex.ts index 28b4d506a..d323b3ee6 100644 --- a/quartz/plugins/transformers/latex.ts +++ b/quartz/plugins/transformers/latex.ts @@ -31,8 +31,10 @@ export const Latex: QuartzTransformerPlugin> = (opts) => { if (engine === "katex") { return { css: [ - // base css - "https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.9/katex.min.css", + { + // base css + content: "https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.16.9/katex.min.css", + }, ], js: [ { diff --git a/quartz/util/resources.tsx b/quartz/util/resources.tsx index a572d891f..72ae9e63e 100644 --- a/quartz/util/resources.tsx +++ b/quartz/util/resources.tsx @@ -16,6 +16,12 @@ export type JSResource = { } ) +export type CSSResource = { + content: string + inline?: boolean + spaPreserve?: boolean +} + export function JSResourceToScriptElement(resource: JSResource, preserve?: boolean): JSX.Element { const scriptType = resource.moduleType ?? "application/javascript" const spaPreserve = preserve ?? resource.spaPreserve @@ -36,7 +42,24 @@ export function JSResourceToScriptElement(resource: JSResource, preserve?: boole } } +export function CSSResourceToStyleElement(resource: CSSResource, preserve?: boolean): JSX.Element { + const spaPreserve = preserve ?? resource.spaPreserve + if (resource.inline ?? false) { + return + } else { + return ( + + ) + } +} + export interface StaticResources { - css: string[] + css: CSSResource[] js: JSResource[] }