From 341b49cd68e8d819eee99d132b5a815f991f2efd Mon Sep 17 00:00:00 2001 From: Lorenzo Lewis Date: Sat, 5 Aug 2023 12:07:14 +0100 Subject: [PATCH] Add Prettier formatting (#1360) * add prettier Signed-off-by: Lorenzo Lewis * add prettier script Signed-off-by: Lorenzo Lewis * add prettier configs Signed-off-by: Lorenzo Lewis * add git modules to ignore Signed-off-by: Lorenzo Lewis * ignore formatting autogenerated references Signed-off-by: Lorenzo Lewis * format Signed-off-by: Lorenzo Lewis * add format workflow for testing Signed-off-by: Lorenzo Lewis * set package manager Signed-off-by: Lorenzo Lewis * valid package manager? Signed-off-by: Lorenzo Lewis * test applying formatting Signed-off-by: Lorenzo Lewis * [ci] format * update action target branch Signed-off-by: Lorenzo Lewis * line break Signed-off-by: Lorenzo Lewis --------- Signed-off-by: Lorenzo Lewis Co-authored-by: lorenzolewis --- .github/workflows/format.yml | 34 + .prettierignore | 14 + .prettierrc | 23 + astro.config.mjs | 258 ++--- locales.json | 2 +- package.json | 4 + packages/i18n-tracker/build.ts | 24 +- .../lib/translation-status/builder.ts | 815 ++++++++------- .../lib/translation-status/template.html | 6 +- .../lib/translation-status/types.ts | 40 +- packages/js-api-generator/build.ts | 391 ++++---- pnpm-lock.yaml | 21 + src/components/Feedback.astro | 16 +- src/components/Stub.astro | 28 +- src/content/config.ts | 4 +- src/content/docs/2/guide/create/mobile.mdx | 74 +- src/content/docs/2/guide/index.mdx | 4 +- src/content/docs/index.mdx | 56 +- src/plugins/configGenerator.ts | 932 +++++++++--------- src/styles/custom.css | 328 +++--- 20 files changed, 1536 insertions(+), 1538 deletions(-) create mode 100644 .github/workflows/format.yml create mode 100644 .prettierignore create mode 100644 .prettierrc diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml new file mode 100644 index 000000000..115492256 --- /dev/null +++ b/.github/workflows/format.yml @@ -0,0 +1,34 @@ +# Adapted from https://github.com/withastro/starlight/blob/main/.github/workflows/format.yml + +name: Format + +on: + push: + branches: + - next + +jobs: + format: + runs-on: ubuntu-latest + steps: + - name: Check out code using Git + uses: actions/checkout@v3 + with: + ref: ${{ github.head_ref }} + # Needs access to push to main + token: ${{ secrets.ORG_TAURI_BOT_PAT }} + - uses: pnpm/action-setup@v2 + - uses: actions/setup-node@v3 + with: + node-version: 16 + cache: 'pnpm' + - run: pnpm i + - name: Format with Prettier + run: pnpm format + - name: Commit changes + uses: stefanzweifel/git-auto-commit-action@v4 + with: + commit_message: '[ci] format' + branch: ${{ github.head_ref }} + commit_user_name: fredkbot + commit_user_email: fred+astrobot@astro.build diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 000000000..63c9e7ce5 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,14 @@ +# Deep Directories +**/node_modules + +# Generated Directories +**/dist +**/.astro +src/content/docs/2/reference + +# Git Modules +packages/tauri +packages/plugins-workspace + +# Files +pnpm-lock.yaml diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 000000000..16d46236a --- /dev/null +++ b/.prettierrc @@ -0,0 +1,23 @@ +{ + "printWidth": 100, + "semi": true, + "singleQuote": true, + "tabWidth": 2, + "trailingComma": "es5", + "useTabs": true, + "plugins": ["prettier-plugin-astro"], + "overrides": [ + { + "files": [".*", "*.json", "*.md", "*.toml", "*.yml"], + "options": { + "useTabs": false + } + }, + { + "files": ["*.md", "*.mdx"], + "options": { + "printWidth": 80 + } + } + ] +} diff --git a/astro.config.mjs b/astro.config.mjs index 27896cee5..2ad7981ef 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -9,133 +9,133 @@ await configGenerator(); // https://astro.build/config export default defineConfig({ - site: 'https://beta.tauri.app', - compressHTML: true, - build: { - inlineStylesheets: 'always', - }, - integrations: [ - starlight({ - title: 'Tauri', - description: 'The cross-platform app building toolkit', - logo: { - src: './src/assets/logo.svg', - // light: './src/assets/logo_light.svg', - replacesTitle: true, - }, - social: { - github: 'https://github.com/tauri-apps/tauri', - discord: 'https://discord.com/invite/tauri', - twitter: 'https://twitter.com/TauriApps', - mastodon: 'https://fosstodon.org/@TauriApps', - }, - editLink: { - baseUrl: 'https://github.com/tauri-apps/tauri-docs/edit/starlight', - }, - customCss: ['./src/styles/custom.css'], - sidebar: [ - { - label: 'Quick Start', - items: [ - { label: 'Why Tauri?', link: '/2/guide/' }, - { label: 'Prerequisites', link: '/2/guide/prerequisites' }, - { - label: 'Create a Project', - link: '/2/guide/create/', - }, - { - label: 'Upgrade & Migrate', - link: '2/guide/upgrade-migrate', - }, - { - label: 'Core Concepts', - link: '2/guide/core-concepts', - }, - { - label: 'Plugins', - link: '2/guide/plugins', - }, - ], - }, - { - label: 'Guides', - items: [ - { - label: 'Develop', - link: '2/guide/develop', - }, - { - label: 'Debug', - link: '2/guide/debug', - }, - { - label: 'Test', - link: '2/guide/test', - }, - { - label: 'Build & Distribute', - link: '2/guide/build-distribute', - }, - { - label: 'Troubleshoot', - link: '2/guide/troubleshoot', - }, - ], - }, - { - label: 'Features & Recipes', - link: '2/recipe', - }, - { - label: 'References', - items: [ - { - label: 'Configuration', - link: '2/reference/config', - }, - { - label: 'Command Line Interface (CLI)', - link: '2/reference/cli', - }, - { - label: 'Core JavaScript API', - link: '2/reference/core/js', - }, - { - label: 'Core Rust API (via Docs.rs)', - // TODO: Is there a way to link this to the latest pre-released version? - link: 'https://docs.rs/tauri/~2.0.0-alpha', - }, - { - label: 'Plugin References', - link: '2/reference/plugin', - }, - ], - }, - { - label: 'Tauri v1', - link: 'https://tauri.app', - }, - ], - locales, - lastUpdated: true, - }), - ], - markdown: { - shikiConfig: { - langs: ['powershell'], - }, - rehypePlugins: [ - rehypeHeadingIds, - [ - rehypeAutolinkHeadings, - { - behavior: 'wrap', - properties: { ariaHidden: true, tabIndex: -1, class: 'heading-link' }, - }, - ], - ], - }, - // Process images with sharp: https://docs.astro.build/en/guides/assets/#using-sharp - image: { service: { entrypoint: 'astro/assets/services/sharp' } }, + site: 'https://beta.tauri.app', + compressHTML: true, + build: { + inlineStylesheets: 'always', + }, + integrations: [ + starlight({ + title: 'Tauri', + description: 'The cross-platform app building toolkit', + logo: { + src: './src/assets/logo.svg', + // light: './src/assets/logo_light.svg', + replacesTitle: true, + }, + social: { + github: 'https://github.com/tauri-apps/tauri', + discord: 'https://discord.com/invite/tauri', + twitter: 'https://twitter.com/TauriApps', + mastodon: 'https://fosstodon.org/@TauriApps', + }, + editLink: { + baseUrl: 'https://github.com/tauri-apps/tauri-docs/edit/starlight', + }, + customCss: ['./src/styles/custom.css'], + sidebar: [ + { + label: 'Quick Start', + items: [ + { label: 'Why Tauri?', link: '/2/guide/' }, + { label: 'Prerequisites', link: '/2/guide/prerequisites' }, + { + label: 'Create a Project', + link: '/2/guide/create/', + }, + { + label: 'Upgrade & Migrate', + link: '2/guide/upgrade-migrate', + }, + { + label: 'Core Concepts', + link: '2/guide/core-concepts', + }, + { + label: 'Plugins', + link: '2/guide/plugins', + }, + ], + }, + { + label: 'Guides', + items: [ + { + label: 'Develop', + link: '2/guide/develop', + }, + { + label: 'Debug', + link: '2/guide/debug', + }, + { + label: 'Test', + link: '2/guide/test', + }, + { + label: 'Build & Distribute', + link: '2/guide/build-distribute', + }, + { + label: 'Troubleshoot', + link: '2/guide/troubleshoot', + }, + ], + }, + { + label: 'Features & Recipes', + link: '2/recipe', + }, + { + label: 'References', + items: [ + { + label: 'Configuration', + link: '2/reference/config', + }, + { + label: 'Command Line Interface (CLI)', + link: '2/reference/cli', + }, + { + label: 'Core JavaScript API', + link: '2/reference/core/js', + }, + { + label: 'Core Rust API (via Docs.rs)', + // TODO: Is there a way to link this to the latest pre-released version? + link: 'https://docs.rs/tauri/~2.0.0-alpha', + }, + { + label: 'Plugin References', + link: '2/reference/plugin', + }, + ], + }, + { + label: 'Tauri v1', + link: 'https://tauri.app', + }, + ], + locales, + lastUpdated: true, + }), + ], + markdown: { + shikiConfig: { + langs: ['powershell'], + }, + rehypePlugins: [ + rehypeHeadingIds, + [ + rehypeAutolinkHeadings, + { + behavior: 'wrap', + properties: { ariaHidden: true, tabIndex: -1, class: 'heading-link' }, + }, + ], + ], + }, + // Process images with sharp: https://docs.astro.build/en/guides/assets/#using-sharp + image: { service: { entrypoint: 'astro/assets/services/sharp' } }, }); diff --git a/locales.json b/locales.json index c0fb140a0..414d7a583 100644 --- a/locales.json +++ b/locales.json @@ -7,4 +7,4 @@ "label": "FranΓ§ais", "lang": "fr" } -} \ No newline at end of file +} diff --git a/package.json b/package.json index a09121559..603beddd5 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "dev:setup:plugins-workspace": "pnpm --prefix packages/plugins-workspace install", "dev:setup": "pnpm dev:setup:submodules && pnpm dev:setup:tauri && pnpm dev:setup:plugins-workspace", "dev": "astro dev", + "format": "prettier -w --cache --plugin prettier-plugin-astro .", "build:reference": "pnpm --filter js-api-generator run build", "build:astro": "astro build", "build:i18n": "pnpm --filter docs-i18n-tracker run build", @@ -22,9 +23,12 @@ "@types/json-schema": "^7.0.12", "astro": "^2.10.1", "astro-feelback": "^0.3.4", + "prettier": "^3.0.1", + "prettier-plugin-astro": "^0.11.0", "rehype-autolink-headings": "^6.1.1", "sharp": "^0.32.4" }, + "packageManager": "pnpm@8.2.0", "pnpm": { "patchedDependencies": { "typedoc-plugin-markdown@4.0.0-next.17": "patches/typedoc-plugin-markdown@4.0.0-next.17.patch" diff --git a/packages/i18n-tracker/build.ts b/packages/i18n-tracker/build.ts index ed428a662..da3beeb33 100644 --- a/packages/i18n-tracker/build.ts +++ b/packages/i18n-tracker/build.ts @@ -2,18 +2,18 @@ import { TranslationStatusBuilder } from './lib/translation-status/builder'; import locales from '../../locales.json'; const translationStatusBuilder = new TranslationStatusBuilder({ - pageSourceDir: '../../src/content/docs', - htmlOutputFilePath: '../../dist/contribute/translate-status.html', - sourceLanguage: 'en', - targetLanguages: Object.values(locales) - .map((el) => el.lang) - .filter((lang) => lang !== 'en') - .sort(), - languageLabels: Object.values(locales) - .filter((loc) => loc.lang !== 'en') - .reduce((acc, curr) => ({ [curr.lang]: curr.label, ...acc }), {}), - githubRepo: process.env.GITHUB_REPOSITORY || 'tauri-apps/tauri-docs', - githubToken: process.env.GITHUB_TOKEN, + pageSourceDir: '../../src/content/docs', + htmlOutputFilePath: '../../dist/contribute/translate-status.html', + sourceLanguage: 'en', + targetLanguages: Object.values(locales) + .map((el) => el.lang) + .filter((lang) => lang !== 'en') + .sort(), + languageLabels: Object.values(locales) + .filter((loc) => loc.lang !== 'en') + .reduce((acc, curr) => ({ [curr.lang]: curr.label, ...acc }), {}), + githubRepo: process.env.GITHUB_REPOSITORY || 'tauri-apps/tauri-docs', + githubToken: process.env.GITHUB_TOKEN, }); await translationStatusBuilder.run(); diff --git a/packages/i18n-tracker/lib/translation-status/builder.ts b/packages/i18n-tracker/lib/translation-status/builder.ts index a8e5419c1..4fc93fd14 100644 --- a/packages/i18n-tracker/lib/translation-status/builder.ts +++ b/packages/i18n-tracker/lib/translation-status/builder.ts @@ -13,11 +13,11 @@ import type { PageData, PageIndex, PageTranslationStatus } from './types'; export const COMMIT_IGNORE = /(en-only|typo|broken link|i18nReady|i18nIgnore)/i; interface PullRequest { - html_url: string; - title: string; - labels: { - name: string; - }[]; + html_url: string; + title: string; + labels: { + name: string; + }[]; } /** @@ -27,489 +27,452 @@ interface PullRequest { * This code is designed to be run on every push to the `main` branch. */ export class TranslationStatusBuilder { - constructor(config: { - pageSourceDir: string; - /** - * Full path & file name of the HTML file that the translation status should be written to. - * If the parent path does not exist yet, it will be created. - * */ - htmlOutputFilePath: string; - sourceLanguage: string; - targetLanguages: string[]; - languageLabels: { [key: string]: string }; - githubRepo: string; - githubToken?: string | undefined; - }) { - this.pageSourceDir = config.pageSourceDir; - this.htmlOutputFilePath = path.resolve(config.htmlOutputFilePath); - this.sourceLanguage = config.sourceLanguage; - this.targetLanguages = config.targetLanguages; - this.languageLabels = config.languageLabels; - this.githubRepo = config.githubRepo; - this.githubToken = config.githubToken ?? ''; - this.git = simpleGit({ - maxConcurrentProcesses: Math.max(2, Math.min(32, os.cpus().length)), - }); - } + constructor(config: { + pageSourceDir: string; + /** + * Full path & file name of the HTML file that the translation status should be written to. + * If the parent path does not exist yet, it will be created. + * */ + htmlOutputFilePath: string; + sourceLanguage: string; + targetLanguages: string[]; + languageLabels: { [key: string]: string }; + githubRepo: string; + githubToken?: string | undefined; + }) { + this.pageSourceDir = config.pageSourceDir; + this.htmlOutputFilePath = path.resolve(config.htmlOutputFilePath); + this.sourceLanguage = config.sourceLanguage; + this.targetLanguages = config.targetLanguages; + this.languageLabels = config.languageLabels; + this.githubRepo = config.githubRepo; + this.githubToken = config.githubToken ?? ''; + this.git = simpleGit({ + maxConcurrentProcesses: Math.max(2, Math.min(32, os.cpus().length)), + }); + } - readonly pageSourceDir; - readonly htmlOutputFilePath; - readonly sourceLanguage; - readonly targetLanguages; - readonly languageLabels; - readonly githubRepo; - readonly githubToken; - readonly git; + readonly pageSourceDir; + readonly htmlOutputFilePath; + readonly sourceLanguage; + readonly targetLanguages; + readonly languageLabels; + readonly githubRepo; + readonly githubToken; + readonly git; - async run() { - // Before we start, validate that this is not a shallow clone of the repo - const isShallowRepo = await this.git.revparse(['--is-shallow-repository']); - if (isShallowRepo !== 'false') { - output.error(dedent`This script cannot operate on a shallow clone of the git repository. + async run() { + // Before we start, validate that this is not a shallow clone of the repo + const isShallowRepo = await this.git.revparse(['--is-shallow-repository']); + if (isShallowRepo !== 'false') { + output.error(dedent`This script cannot operate on a shallow clone of the git repository. Please add the checkout setting "fetch-depth: 0" to your GitHub workflow: - name: Checkout uses: actions/checkout@v3 with: fetch-depth: 0 `); - process.exit(1); - } + process.exit(1); + } - output.debug(`*** Building translation status`); + output.debug(`*** Building translation status`); - // Ensure that the output directory exists before continuing - output.debug(`- Output file path: ${this.htmlOutputFilePath}`); - const outputDir = path.dirname(this.htmlOutputFilePath); - if (!fs.existsSync(outputDir)) { - fs.mkdirSync(outputDir, { recursive: true }); - } + // Ensure that the output directory exists before continuing + output.debug(`- Output file path: ${this.htmlOutputFilePath}`); + const outputDir = path.dirname(this.htmlOutputFilePath); + if (!fs.existsSync(outputDir)) { + fs.mkdirSync(outputDir, { recursive: true }); + } - // Create an index of all Markdown/MDX pages grouped by language, - // with information about the last minor & major commit per page - output.debug(`- Generating page index...`); - const pages = await this.createPageIndex(); + // Create an index of all Markdown/MDX pages grouped by language, + // with information about the last minor & major commit per page + output.debug(`- Generating page index...`); + const pages = await this.createPageIndex(); - // Determine translation status by source page - const statusByPage = this.getTranslationStatusByPage(pages); + // Determine translation status by source page + const statusByPage = this.getTranslationStatusByPage(pages); - // Fetch all pull requests - const pullRequests = await this.getPullRequests(); + // Fetch all pull requests + const pullRequests = await this.getPullRequests(); - // Render a human-friendly summary - output.debug(`- Building HTML file...`); - const html = this.renderHtmlStatusPage(statusByPage, pullRequests); + // Render a human-friendly summary + output.debug(`- Building HTML file...`); + const html = this.renderHtmlStatusPage(statusByPage, pullRequests); - // Write HTML output to file - fs.writeFileSync(this.htmlOutputFilePath, html); + // Write HTML output to file + fs.writeFileSync(this.htmlOutputFilePath, html); - output.debug(''); - output.debug('*** Success!'); - output.debug(''); - } + output.debug(''); + output.debug('*** Success!'); + output.debug(''); + } - /** Get all pull requests with the `i18n` tag */ - async getPullRequests() { - const pullRequests: PullRequest[] = await githubGet({ - url: `https://api.github.com/repos/${this.githubRepo}/pulls?state=open&per_page=100`, - githubToken: this.githubToken, - }); + /** Get all pull requests with the `i18n` tag */ + async getPullRequests() { + const pullRequests: PullRequest[] = await githubGet({ + url: `https://api.github.com/repos/${this.githubRepo}/pulls?state=open&per_page=100`, + githubToken: this.githubToken, + }); - return pullRequests.filter((pr) => - pr.labels.find((label) => label.name === 'i18n') - ); - } + return pullRequests.filter((pr) => pr.labels.find((label) => label.name === 'i18n')); + } - async createPageIndex(): Promise { - // Initialize a new page index with a stable key order - const pages: PageIndex = { - [this.sourceLanguage]: {}, - }; - this.targetLanguages.forEach((lang) => (pages[lang] = {})); + async createPageIndex(): Promise { + // Initialize a new page index with a stable key order + const pages: PageIndex = { + [this.sourceLanguage]: {}, + }; + this.targetLanguages.forEach((lang) => (pages[lang] = {})); - // Enumerate all markdown pages with supported languages in pageSourceDir, - // retrieve their page data and update them - const pagePaths = await glob(`**/*.{md,mdx}`, { - cwd: this.pageSourceDir, - }); - const updatedPages = await Promise.all( - pagePaths.sort().map(async (pagePath) => { - const pathParts = pagePath.split('/'); - const isLanguageSubpathIncluded = this.targetLanguages.includes( - pathParts[0]! - ); + // Enumerate all markdown pages with supported languages in pageSourceDir, + // retrieve their page data and update them + const pagePaths = await glob(`**/*.{md,mdx}`, { + cwd: this.pageSourceDir, + }); + const updatedPages = await Promise.all( + pagePaths.sort().map(async (pagePath) => { + const pathParts = pagePath.split('/'); + const isLanguageSubpathIncluded = this.targetLanguages.includes(pathParts[0]!); - // If the first path of a file does not belong to a language, it will be by default a page of the original language set. - const lang = isLanguageSubpathIncluded - ? pathParts[0] - : this.sourceLanguage; - const subpath = pathParts.splice(1).join('/'); + // If the first path of a file does not belong to a language, it will be by default a page of the original language set. + const lang = isLanguageSubpathIncluded ? pathParts[0] : this.sourceLanguage; + const subpath = pathParts.splice(1).join('/'); - // Create or update page data for the page - return { - lang, - subpath: isLanguageSubpathIncluded ? subpath : pagePath, - pageData: await this.getSinglePageData(pagePath), - }; - }) - ); + // Create or update page data for the page + return { + lang, + subpath: isLanguageSubpathIncluded ? subpath : pagePath, + pageData: await this.getSinglePageData(pagePath), + }; + }) + ); - // Write the updated pages to the index - updatedPages.forEach((page) => { - if (!page) return; - const { lang, subpath, pageData } = page; - if (!pageData) return; - pages[lang!]![subpath] = pageData; - }); + // Write the updated pages to the index + updatedPages.forEach((page) => { + if (!page) return; + const { lang, subpath, pageData } = page; + if (!pageData) return; + pages[lang!]![subpath] = pageData; + }); - return pages; - } + return pages; + } - /** - * Processes the markdown page located in the pageSourceDir subpath `pagePath` - * and creates a new page data object based on its frontmatter and git history. - */ - async getSinglePageData(pagePath: string): Promise { - const fullFilePath = `${this.pageSourceDir}/${pagePath}`; + /** + * Processes the markdown page located in the pageSourceDir subpath `pagePath` + * and creates a new page data object based on its frontmatter and git history. + */ + async getSinglePageData(pagePath: string): Promise { + const fullFilePath = `${this.pageSourceDir}/${pagePath}`; - // Retrieve git history for the current page - const gitHistory = await this.getGitHistory(fullFilePath); + // Retrieve git history for the current page + const gitHistory = await this.getGitHistory(fullFilePath); - if (!gitHistory) return; + if (!gitHistory) return; - // Retrieve i18nReady flag from frontmatter - const frontMatterBlock = tryGetFrontMatterBlock(fullFilePath); - const i18nReady = /^\s*i18nReady:\s*true\s*$/m.test(frontMatterBlock); + // Retrieve i18nReady flag from frontmatter + const frontMatterBlock = tryGetFrontMatterBlock(fullFilePath); + const i18nReady = /^\s*i18nReady:\s*true\s*$/m.test(frontMatterBlock); - return { - ...(i18nReady ? { i18nReady: true } : {}), - lastChange: gitHistory.lastCommitDate, - lastCommitMsg: gitHistory.lastCommitMessage, - lastMajorChange: gitHistory.lastMajorCommitDate, - lastMajorCommitMsg: gitHistory.lastMajorCommitMessage, - }; - } + return { + ...(i18nReady ? { i18nReady: true } : {}), + lastChange: gitHistory.lastCommitDate, + lastCommitMsg: gitHistory.lastCommitMessage, + lastMajorChange: gitHistory.lastMajorCommitDate, + lastMajorCommitMsg: gitHistory.lastMajorCommitMessage, + }; + } - async getGitHistory(filePath: string) { - const gitLog = await this.git.log({ - file: filePath, - strictDate: true, - }); + async getGitHistory(filePath: string) { + const gitLog = await this.git.log({ + file: filePath, + strictDate: true, + }); - const lastCommit = gitLog.latest; - if (!lastCommit) { - return; - // Disabled since we have generated reference files - // throw new Error(dedent`Failed to retrieve last commit information for file - // "${filePath}". Your working copy should not contain uncommitted new pages - // when running this script.`); - } + const lastCommit = gitLog.latest; + if (!lastCommit) { + return; + // Disabled since we have generated reference files + // throw new Error(dedent`Failed to retrieve last commit information for file + // "${filePath}". Your working copy should not contain uncommitted new pages + // when running this script.`); + } - // Attempt to find the last "major" commit, ignoring any commits that - // usually do not require translations to be updated - const lastMajorCommit = - gitLog.all.find((logEntry) => { - return !logEntry.message.match(COMMIT_IGNORE); - }) || lastCommit; + // Attempt to find the last "major" commit, ignoring any commits that + // usually do not require translations to be updated + const lastMajorCommit = + gitLog.all.find((logEntry) => { + return !logEntry.message.match(COMMIT_IGNORE); + }) || lastCommit; - return { - lastCommitMessage: lastCommit.message, - lastCommitDate: toUtcString(lastCommit.date), - lastMajorCommitMessage: lastMajorCommit.message, - lastMajorCommitDate: toUtcString(lastMajorCommit.date), - }; - } + return { + lastCommitMessage: lastCommit.message, + lastCommitDate: toUtcString(lastCommit.date), + lastMajorCommitMessage: lastMajorCommit.message, + lastMajorCommitDate: toUtcString(lastMajorCommit.date), + }; + } - getTranslationStatusByPage(pages: PageIndex): PageTranslationStatus[] { - const sourcePages = pages[this.sourceLanguage]; - const arrContent: PageTranslationStatus[] = []; + getTranslationStatusByPage(pages: PageIndex): PageTranslationStatus[] { + const sourcePages = pages[this.sourceLanguage]; + const arrContent: PageTranslationStatus[] = []; - Object.keys(sourcePages!).forEach((subpath) => { - const sourcePage = sourcePages![subpath]!; - if (!sourcePage.i18nReady) return; + Object.keys(sourcePages!).forEach((subpath) => { + const sourcePage = sourcePages![subpath]!; + if (!sourcePage.i18nReady) return; - const content: PageTranslationStatus = { - subpath, - sourcePage, - githubUrl: this.getPageUrl({ lang: this.sourceLanguage, subpath }), - translations: {}, - }; + const content: PageTranslationStatus = { + subpath, + sourcePage, + githubUrl: this.getPageUrl({ lang: this.sourceLanguage, subpath }), + translations: {}, + }; - this.targetLanguages.forEach((lang) => { - const i18nPage = pages[lang]![subpath]!; - content.translations[lang] = { - page: i18nPage, - isMissing: !i18nPage, - isOutdated: - i18nPage && sourcePage.lastMajorChange > i18nPage.lastMajorChange, - githubUrl: this.getPageUrl({ lang, subpath }), - sourceHistoryUrl: this.getPageUrl({ - lang: 'en', - subpath, - type: 'commits', - query: i18nPage ? `?since=${i18nPage.lastMajorChange}` : '', - }), - }; - }); + this.targetLanguages.forEach((lang) => { + const i18nPage = pages[lang]![subpath]!; + content.translations[lang] = { + page: i18nPage, + isMissing: !i18nPage, + isOutdated: i18nPage && sourcePage.lastMajorChange > i18nPage.lastMajorChange, + githubUrl: this.getPageUrl({ lang, subpath }), + sourceHistoryUrl: this.getPageUrl({ + lang: 'en', + subpath, + type: 'commits', + query: i18nPage ? `?since=${i18nPage.lastMajorChange}` : '', + }), + }; + }); - arrContent.push(content); - }); + arrContent.push(content); + }); - return arrContent; - } + return arrContent; + } - getPageUrl({ - type = 'blob', - refName = 'main', - lang, - subpath, - query = '', - }: { - type?: string; - refName?: string; - lang: string; - subpath: string; - query?: string; - }) { - const noDotSrcDir = this.pageSourceDir.replace(/^\.+\//, ''); - const isSrcLang = lang === this.sourceLanguage; - return `https://github.com/${ - this.githubRepo - }/${type}/${refName}/${noDotSrcDir}${ - isSrcLang ? '' : `/${lang}` - }/${subpath}${query}`; - } + getPageUrl({ + type = 'blob', + refName = 'main', + lang, + subpath, + query = '', + }: { + type?: string; + refName?: string; + lang: string; + subpath: string; + query?: string; + }) { + const noDotSrcDir = this.pageSourceDir.replace(/^\.+\//, ''); + const isSrcLang = lang === this.sourceLanguage; + return `https://github.com/${this.githubRepo}/${type}/${refName}/${noDotSrcDir}${ + isSrcLang ? '' : `/${lang}` + }/${subpath}${query}`; + } - /** - * Renders the primary HTML output of this script by loading a template from disk, - * rendering the individual views to HTML, and inserting them into the template. - */ - renderHtmlStatusPage( - statusByPage: PageTranslationStatus[], - prs: PullRequest[] - ) { - // Load HTML template - const templateFilePath = path.join( - path.dirname(fileURLToPath(import.meta.url)), - 'template.html' - ); - const html = fs.readFileSync(templateFilePath, { encoding: 'utf8' }); + /** + * Renders the primary HTML output of this script by loading a template from disk, + * rendering the individual views to HTML, and inserting them into the template. + */ + renderHtmlStatusPage(statusByPage: PageTranslationStatus[], prs: PullRequest[]) { + // Load HTML template + const templateFilePath = path.join( + path.dirname(fileURLToPath(import.meta.url)), + 'template.html' + ); + const html = fs.readFileSync(templateFilePath, { encoding: 'utf8' }); - // Replace placeholders in the template with the rendered views - // and return the resulting HTML page - return html - .replace( - '', - this.renderTranslationStatusByLanguage(statusByPage) - ) - .replace( - '', - this.renderTranslationNeedsReview(prs) - ) - .replace( - '', - this.renderTranslationStatusByPage(statusByPage) - ); - } + // Replace placeholders in the template with the rendered views + // and return the resulting HTML page + return html + .replace( + '', + this.renderTranslationStatusByLanguage(statusByPage) + ) + .replace('', this.renderTranslationNeedsReview(prs)) + .replace( + '', + this.renderTranslationStatusByPage(statusByPage) + ); + } - renderTranslationStatusByLanguage(statusByPage: PageTranslationStatus[]) { - const lines: string[] = []; + renderTranslationStatusByLanguage(statusByPage: PageTranslationStatus[]) { + const lines: string[] = []; - this.targetLanguages.forEach((lang) => { - const missing = statusByPage.filter( - (content) => content.translations[lang]!.isMissing - ); - const outdated = statusByPage.filter( - (content) => content.translations[lang]!.isOutdated - ); - lines.push('
'); - lines.push( - `` + - `${this.languageLabels[lang]} (${lang})` + - `
` + - `` + - `${statusByPage.length - outdated.length - missing.length} done, ` + - `${outdated.length} need${ - outdated.length === 1 ? 's' : '' - } updating, ` + - `${missing.length} missing` + - `` + - '
' + - this.renderProgressBar( - statusByPage.length, - outdated.length, - missing.length - ) + - `
` - ); - lines.push(``); - if (outdated.length > 0) { - lines.push(`
πŸ”„  Needs updating
`); - lines.push(`
    `); - lines.push( - ...outdated.map( - (content) => - `
  • ` + - `${this.renderLink(content.githubUrl, content.subpath)} ` + - `(${this.renderLink( - content.translations[lang]!.githubUrl, - 'outdated translation' - )}, ${this.renderLink( - content.translations[lang]!.sourceHistoryUrl, - 'source change history' - )})` + - `
  • ` - ) - ); - lines.push(`
`); - } - if (missing.length > 0) { - lines.push(`
❌  Missing
`); - lines.push(`
    `); - lines.push( - ...missing.map( - (content) => - `
  • ` + - `${this.renderLink( - content.githubUrl, - content.subpath - )}   ${this.renderCreatePageButton(lang, content.subpath)}` + - `
  • ` - ) - ); - lines.push(`
`); - } - lines.push(`
`); - lines.push(``); - }); + this.targetLanguages.forEach((lang) => { + const missing = statusByPage.filter((content) => content.translations[lang]!.isMissing); + const outdated = statusByPage.filter((content) => content.translations[lang]!.isOutdated); + lines.push('
'); + lines.push( + `` + + `${this.languageLabels[lang]} (${lang})` + + `
` + + `` + + `${statusByPage.length - outdated.length - missing.length} done, ` + + `${outdated.length} need${outdated.length === 1 ? 's' : ''} updating, ` + + `${missing.length} missing` + + `` + + '
' + + this.renderProgressBar(statusByPage.length, outdated.length, missing.length) + + `
` + ); + lines.push(``); + if (outdated.length > 0) { + lines.push(`
πŸ”„  Needs updating
`); + lines.push(`
    `); + lines.push( + ...outdated.map( + (content) => + `
  • ` + + `${this.renderLink(content.githubUrl, content.subpath)} ` + + `(${this.renderLink( + content.translations[lang]!.githubUrl, + 'outdated translation' + )}, ${this.renderLink( + content.translations[lang]!.sourceHistoryUrl, + 'source change history' + )})` + + `
  • ` + ) + ); + lines.push(`
`); + } + if (missing.length > 0) { + lines.push(`
❌  Missing
`); + lines.push(`
    `); + lines.push( + ...missing.map( + (content) => + `
  • ` + + `${this.renderLink( + content.githubUrl, + content.subpath + )}   ${this.renderCreatePageButton(lang, content.subpath)}` + + `
  • ` + ) + ); + lines.push(`
`); + } + lines.push(`
`); + lines.push(``); + }); - return lines.join('\n'); - } + return lines.join('\n'); + } - renderTranslationNeedsReview(prs: PullRequest[]) { - const lines: string[] = []; + renderTranslationNeedsReview(prs: PullRequest[]) { + const lines: string[] = []; - if (prs.length > 0) { - lines.push(`
    `); - lines.push( - ...prs.map((pr) => { - const title = pr.title.replaceAll('`', ''); - return `
  • ` + this.renderLink(pr.html_url, title) + `
  • `; - }) - ); - lines.push(`
`); - } - lines.push(``); + if (prs.length > 0) { + lines.push(`
    `); + lines.push( + ...prs.map((pr) => { + const title = pr.title.replaceAll('`', ''); + return `
  • ` + this.renderLink(pr.html_url, title) + `
  • `; + }) + ); + lines.push(`
`); + } + lines.push(``); - return lines.join('\n'); - } + return lines.join('\n'); + } - renderTranslationStatusByPage(statusByPage: PageTranslationStatus[]) { - const lines: string[] = []; + renderTranslationStatusByPage(statusByPage: PageTranslationStatus[]) { + const lines: string[] = []; - lines.push('
'); - lines.push(''); + lines.push('
'); + lines.push('
'); - lines.push(''); - lines.push( - ['Page', ...this.targetLanguages].map((col) => ``).join('') - ); - lines.push(''); + lines.push(''); + lines.push(['Page', ...this.targetLanguages].map((col) => ``).join('')); + lines.push(''); - lines.push(''); - const spacer = `\n${this.targetLanguages - .map(() => ``) - .join('\n')}\n`; - lines.push(spacer); - statusByPage.forEach((content) => { - const cols = []; - cols.push(this.renderLink(content.githubUrl, content.subpath)); - cols.push( - ...this.targetLanguages.map((lang) => { - const translation = content.translations[lang]!; - if (translation.isMissing) - return ``; - if (translation.isOutdated) - return ``; - return ``; - }) - ); - lines.push( - `\n${cols.map((col) => ``).join('\n')}\n` - ); - }); - lines.push(spacer); - lines.push(''); + lines.push(''); + const spacer = `\n${this.targetLanguages + .map(() => ``) + .join('\n')}\n`; + lines.push(spacer); + statusByPage.forEach((content) => { + const cols = []; + cols.push(this.renderLink(content.githubUrl, content.subpath)); + cols.push( + ...this.targetLanguages.map((lang) => { + const translation = content.translations[lang]!; + if (translation.isMissing) + return ``; + if (translation.isOutdated) + return ``; + return ``; + }) + ); + lines.push(`\n${cols.map((col) => ``).join('\n')}\n`); + }); + lines.push(spacer); + lines.push(''); - lines.push('
${col}
${col}
${col}
${col}
'); + lines.push(''); - lines.push( - `\n❌ Missing   πŸ”„ Needs updating   βœ” Completed` - ); - lines.push('
'); + lines.push(`\n❌ Missing   πŸ”„ Needs updating   βœ” Completed`); + lines.push(''); - return lines.join('\n'); - } + return lines.join('\n'); + } - /** - * Render a link to a pre-filled GitHub UI for creating a new file. - * - * @param lang Language tag to create page for - * @param filename Subpath of page to create - */ - renderCreatePageButton(lang: string, filename: string): string { - // We include `lang` twice because GitHub eats the last path segment when setting filename. - const createUrl = new URL( - `https://github.com/${this.githubRepo}/new/main/src/content/docs` - ); - createUrl.searchParams.set('filename', lang + '/' + filename); - createUrl.searchParams.set('value', '---\ntitle:\ndescription:\n---\n'); - return this.renderLink( - createUrl.href, - `Create\xa0page\xa0+`, - 'create-button' - ); - } + /** + * Render a link to a pre-filled GitHub UI for creating a new file. + * + * @param lang Language tag to create page for + * @param filename Subpath of page to create + */ + renderCreatePageButton(lang: string, filename: string): string { + // We include `lang` twice because GitHub eats the last path segment when setting filename. + const createUrl = new URL(`https://github.com/${this.githubRepo}/new/main/src/content/docs`); + createUrl.searchParams.set('filename', lang + '/' + filename); + createUrl.searchParams.set('value', '---\ntitle:\ndescription:\n---\n'); + return this.renderLink(createUrl.href, `Create\xa0page\xa0+`, 'create-button'); + } - /** - * Render a progress bar with emoji. - */ - renderProgressBar( - total: number, - outdated: number, - missing: number, - { size = 20 }: { size?: number } = {} - ) { - const outdatedLength = Math.round((outdated / total) * size); - const missingLength = Math.round((missing / total) * size); - const doneLength = size - outdatedLength - missingLength; - return ( - '' - ); - } + /** + * Render a progress bar with emoji. + */ + renderProgressBar( + total: number, + outdated: number, + missing: number, + { size = 20 }: { size?: number } = {} + ) { + const outdatedLength = Math.round((outdated / total) * size); + const missingLength = Math.round((missing / total) * size); + const doneLength = size - outdatedLength - missingLength; + return ( + '' + ); + } - renderLink(href: string, text: string, className = ''): string { - return `${escape(text)}`; - } + renderLink(href: string, text: string, className = ''): string { + return `${escape(text)}`; + } } function toUtcString(date: string) { - return new Date(date).toISOString(); + return new Date(date).toISOString(); } function tryGetFrontMatterBlock(filePath: string): string { - const contents = fs.readFileSync(filePath, 'utf8'); - const matches = contents.match(/^\s*---([\S\s]*?)\n---/); - if (!matches) return ''; - return matches[1]; + const contents = fs.readFileSync(filePath, 'utf8'); + const matches = contents.match(/^\s*---([\S\s]*?)\n---/); + if (!matches) return ''; + return matches[1]; } diff --git a/packages/i18n-tracker/lib/translation-status/template.html b/packages/i18n-tracker/lib/translation-status/template.html index 919bbc6d0..96a34a005 100644 --- a/packages/i18n-tracker/lib/translation-status/template.html +++ b/packages/i18n-tracker/lib/translation-status/template.html @@ -249,9 +249,9 @@

If you're interested in helping us translate - tauri.app into one of the - languages listed below, you've come to the right place! This auto-updating page always - lists all the content that could use your help right now. + tauri.app into one of the languages listed below, you've + come to the right place! This auto-updating page always lists all the content that could + use your help right now.

diff --git a/packages/i18n-tracker/lib/translation-status/types.ts b/packages/i18n-tracker/lib/translation-status/types.ts index 16d33e631..a245b96c3 100644 --- a/packages/i18n-tracker/lib/translation-status/types.ts +++ b/packages/i18n-tracker/lib/translation-status/types.ts @@ -1,28 +1,28 @@ export type PageIndex = { - [language: string]: { - [pagePath: string]: PageData; - }; + [language: string]: { + [pagePath: string]: PageData; + }; }; export type PageData = { - lastChange: string; - lastCommitMsg: string; - lastMajorChange: string; - lastMajorCommitMsg: string; - i18nReady?: boolean; + lastChange: string; + lastCommitMsg: string; + lastMajorChange: string; + lastMajorCommitMsg: string; + i18nReady?: boolean; }; export type PageTranslationStatus = { - subpath: string; - sourcePage: PageData; - githubUrl: string; - translations: { - [language: string]: { - page: PageData; - isMissing: boolean; - isOutdated: boolean; - githubUrl: string; - sourceHistoryUrl: string; - }; - }; + subpath: string; + sourcePage: PageData; + githubUrl: string; + translations: { + [language: string]: { + page: PageData; + isMissing: boolean; + isOutdated: boolean; + githubUrl: string; + sourceHistoryUrl: string; + }; + }; }; diff --git a/packages/js-api-generator/build.ts b/packages/js-api-generator/build.ts index cf1a00d1b..33e020268 100644 --- a/packages/js-api-generator/build.ts +++ b/packages/js-api-generator/build.ts @@ -1,257 +1,244 @@ import { - Application, - Comment, - DeclarationReflection, - Options, - PageEvent, - Reflection, - SignatureReflection, - TSConfigReader, - type TypeDocOptions, + Application, + Comment, + DeclarationReflection, + Options, + PageEvent, + Reflection, + SignatureReflection, + TSConfigReader, + type TypeDocOptions, } from 'typedoc'; import { - MarkdownTheme, - MarkdownThemeRenderContext, - type PluginOptions, - load as loadMarkdownPlugin, + MarkdownTheme, + MarkdownThemeRenderContext, + type PluginOptions, + load as loadMarkdownPlugin, } from 'typedoc-plugin-markdown'; import path from 'node:path'; import { slug } from 'github-slugger'; import { existsSync } from 'node:fs'; const typeDocConfigBaseOptions: Partial = { - // TypeDoc options - // https://typedoc.org/options/ - githubPages: false, - hideGenerator: true, - theme: 'tauri-theme', - plugin: ['typedoc-plugin-mdn-links'], - // typedoc-plugin-markdown options - // https://github.com/tgreyuk/typedoc-plugin-markdown/blob/next/packages/typedoc-plugin-markdown/docs/usage/options.md - outputFileStrategy: 'modules', - flattenOutputFiles: true, - entryFileName: '../index.md', - // TODO: Pending https://github.com/tgreyuk/typedoc-plugin-markdown/pull/455 being released so that the patch can be removed - indexFileName: 'index.md', - hidePageHeader: true, - hidePageTitle: true, - hideBreadcrumbs: true, - hideInPageTOC: true, - identifiersAsCodeBlocks: true, - propertiesFormat: 'table', - enumMembersFormat: 'table', - typeDeclarationFormat: 'table', + // TypeDoc options + // https://typedoc.org/options/ + githubPages: false, + hideGenerator: true, + theme: 'tauri-theme', + plugin: ['typedoc-plugin-mdn-links'], + // typedoc-plugin-markdown options + // https://github.com/tgreyuk/typedoc-plugin-markdown/blob/next/packages/typedoc-plugin-markdown/docs/usage/options.md + outputFileStrategy: 'modules', + flattenOutputFiles: true, + entryFileName: '../index.md', + // TODO: Pending https://github.com/tgreyuk/typedoc-plugin-markdown/pull/455 being released so that the patch can be removed + indexFileName: 'index.md', + hidePageHeader: true, + hidePageTitle: true, + hideBreadcrumbs: true, + hideInPageTOC: true, + identifiersAsCodeBlocks: true, + propertiesFormat: 'table', + enumMembersFormat: 'table', + typeDeclarationFormat: 'table', }; async function generator() { - if (existsSync('../tauri/tooling/api/node_modules')) { - const coreJsOptions: Partial = { - entryPoints: ['../tauri/tooling/api/src/index.ts'], - tsconfig: '../tauri/tooling/api/tsconfig.json', - gitRevision: 'dev', - baseUrl: '/2/reference/core/js/', - ...typeDocConfigBaseOptions, - }; + if (existsSync('../tauri/tooling/api/node_modules')) { + const coreJsOptions: Partial = { + entryPoints: ['../tauri/tooling/api/src/index.ts'], + tsconfig: '../tauri/tooling/api/tsconfig.json', + gitRevision: 'dev', + baseUrl: '/2/reference/core/js/', + ...typeDocConfigBaseOptions, + }; - await generateDocs(coreJsOptions); - } else { - console.log( - 'Tauri submodule is not initialized, respective API routes will not be rendered.' - ); - } + await generateDocs(coreJsOptions); + } else { + console.log('Tauri submodule is not initialized, respective API routes will not be rendered.'); + } - // TODO: the following plugins don't have a JS API: - // 'localhost', - // 'persisted-scope', - // 'single-instance', + // TODO: the following plugins don't have a JS API: + // 'localhost', + // 'persisted-scope', + // 'single-instance', - const plugins = [ - 'app', - 'authenticator', - 'autostart', - 'cli', - 'clipboard-manager', - 'dialog', - 'fs', - 'global-shortcut', - 'http', - 'log', - 'notification', - 'os', - 'positioner', - 'process', - 'shell', - 'sql', - 'store', - 'stronghold', - 'updater', - 'upload', - 'websocket', - 'window', - 'window-state', - ]; + const plugins = [ + 'app', + 'authenticator', + 'autostart', + 'cli', + 'clipboard-manager', + 'dialog', + 'fs', + 'global-shortcut', + 'http', + 'log', + 'notification', + 'os', + 'positioner', + 'process', + 'shell', + 'sql', + 'store', + 'stronghold', + 'updater', + 'upload', + 'websocket', + 'window', + 'window-state', + ]; - if (existsSync('../plugins-workspace/node_modules')) { - plugins.forEach(async (plugin) => { - const pluginJsOptions: Partial = { - entryPoints: [ - `../plugins-workspace/plugins/${plugin}/guest-js/index.ts`, - ], - tsconfig: `../plugins-workspace/plugins/${plugin}/tsconfig.json`, - gitRevision: 'v2', - baseUrl: `/2/reference/plugin/${plugin}/js`, - ...typeDocConfigBaseOptions, - }; + if (existsSync('../plugins-workspace/node_modules')) { + plugins.forEach(async (plugin) => { + const pluginJsOptions: Partial = { + entryPoints: [`../plugins-workspace/plugins/${plugin}/guest-js/index.ts`], + tsconfig: `../plugins-workspace/plugins/${plugin}/tsconfig.json`, + gitRevision: 'v2', + baseUrl: `/2/reference/plugin/${plugin}/js`, + ...typeDocConfigBaseOptions, + }; - await generateDocs(pluginJsOptions); - }); - } else { - console.log( - 'Plugins workspace submodule is not initialized, respective API routes will not be rendered.' - ); - } + await generateDocs(pluginJsOptions); + }); + } else { + console.log( + 'Plugins workspace submodule is not initialized, respective API routes will not be rendered.' + ); + } } // Adapted from https://github.com/HiDeoo/starlight-typedoc async function generateDocs(options: Partial) { - const outputDir = `../../src/content/docs${options.baseUrl}`; + const outputDir = `../../src/content/docs${options.baseUrl}`; - const app = new Application(); - app.options.addReader(new TSConfigReader()); - app.renderer.defineTheme('tauri-theme', TauriTheme); - loadMarkdownPlugin(app); + const app = new Application(); + app.options.addReader(new TSConfigReader()); + app.renderer.defineTheme('tauri-theme', TauriTheme); + loadMarkdownPlugin(app); - app.renderer.on(PageEvent.END, (event: PageEvent) => { - pageEventEnd(event); - }); + app.renderer.on(PageEvent.END, (event: PageEvent) => { + pageEventEnd(event); + }); - await app.bootstrapWithPlugins(options); - const project = app.convert(); + await app.bootstrapWithPlugins(options); + const project = app.convert(); - if (project) { - await app.generateDocs(project, outputDir); - } + if (project) { + await app.generateDocs(project, outputDir); + } } // Adds frontmatter to the top of the file // Adapted from https://github.com/HiDeoo/starlight-typedoc function pageEventEnd(event: PageEvent) { - if (!event.contents) { - return; - } - const frontmatter = [ - '---', - `title: "${event.model.name}"`, - 'editUrl: false', - 'prev: false', - 'next: false', - '---', - '', - event.contents, - ]; - event.contents = frontmatter.join('\n'); + if (!event.contents) { + return; + } + const frontmatter = [ + '---', + `title: "${event.model.name}"`, + 'editUrl: false', + 'prev: false', + 'next: false', + '---', + '', + event.contents, + ]; + event.contents = frontmatter.join('\n'); } // Overrides and extensions based on https://github.com/tgreyuk/typedoc-plugin-markdown/blob/next/packages/typedoc-plugin-markdown/docs/usage/customizing.md class TauriTheme extends MarkdownTheme { - override getRenderContext( - pageEvent: PageEvent - ): MarkdownThemeRenderContext { - return new TauriThemeRenderContext(pageEvent, this.application.options); - } + override getRenderContext(pageEvent: PageEvent): MarkdownThemeRenderContext { + return new TauriThemeRenderContext(pageEvent, this.application.options); + } } class TauriThemeRenderContext extends MarkdownThemeRenderContext { - #markdownThemeRenderContext: MarkdownThemeRenderContext; + #markdownThemeRenderContext: MarkdownThemeRenderContext; - constructor(event: PageEvent, options: Options) { - super(event, options); - this.#markdownThemeRenderContext = new MarkdownThemeRenderContext( - event, - options - ); - } + constructor(event: PageEvent, options: Options) { + super(event, options); + this.#markdownThemeRenderContext = new MarkdownThemeRenderContext(event, options); + } - // Formats `@since` to be a single line - override comment: ( - comment: Comment, - headingLevel?: number | undefined - ) => string = (comment, headingLevel) => { - const filteredComment = { ...comment } as Comment; - filteredComment.blockTags = []; + // Formats `@since` to be a single line + override comment: (comment: Comment, headingLevel?: number | undefined) => string = ( + comment, + headingLevel + ) => { + const filteredComment = { ...comment } as Comment; + filteredComment.blockTags = []; - const customBlockTags = []; + const customBlockTags = []; - for (const blockTag of comment.blockTags) { - if (blockTag.tag === '@since') { - customBlockTags.push(blockTag); - } else { - filteredComment.blockTags.push(blockTag); - } - } + for (const blockTag of comment.blockTags) { + if (blockTag.tag === '@since') { + customBlockTags.push(blockTag); + } else { + filteredComment.blockTags.push(blockTag); + } + } - let markdown = this.#markdownThemeRenderContext.comment( - filteredComment, - headingLevel - ); + let markdown = this.#markdownThemeRenderContext.comment(filteredComment, headingLevel); - for (const customCommentTag of customBlockTags) { - markdown += `\n**Since**: ${customCommentTag.content - .map((content) => content.text) - .join(', ')}\n\n`; - } + for (const customCommentTag of customBlockTags) { + markdown += `\n**Since**: ${customCommentTag.content + .map((content) => content.text) + .join(', ')}\n\n`; + } - return markdown; - }; + return markdown; + }; - // Formats `@source` to be a single line - override sources: ( - reflection: DeclarationReflection | SignatureReflection, - headingLevel: number - ) => string = (reflection, _) => { - if (!reflection.sources) { - return ''; - } - let label = - reflection.sources.length > 1 ? '**Sources**: ' : '**Source**: '; - const sources = reflection.sources.map( - (source) => `[${source.fileName}:${source.line}](${source.url})` - ); + // Formats `@source` to be a single line + override sources: ( + reflection: DeclarationReflection | SignatureReflection, + headingLevel: number + ) => string = (reflection, _) => { + if (!reflection.sources) { + return ''; + } + let label = reflection.sources.length > 1 ? '**Sources**: ' : '**Source**: '; + const sources = reflection.sources.map( + (source) => `[${source.fileName}:${source.line}](${source.url})` + ); - return label + sources.join(', '); - }; + return label + sources.join(', '); + }; - // Adapted from https://github.com/HiDeoo/starlight-typedoc/blob/d95072e218004276942a5132ec8a4e3561425903/packages/starlight-typedoc/src/libs/theme.ts#L28 - override relativeURL = (url: string | undefined) => { - if (!url) { - return null; - } + // Adapted from https://github.com/HiDeoo/starlight-typedoc/blob/d95072e218004276942a5132ec8a4e3561425903/packages/starlight-typedoc/src/libs/theme.ts#L28 + override relativeURL = (url: string | undefined) => { + if (!url) { + return null; + } - const filePath = path.parse(url); - const [, anchor] = filePath.base.split('#'); - const segments = filePath.dir - .split('/') - .map((segment) => slug(segment)) - .filter((segment) => segment !== ''); + const filePath = path.parse(url); + const [, anchor] = filePath.base.split('#'); + const segments = filePath.dir + .split('/') + .map((segment) => slug(segment)) + .filter((segment) => segment !== ''); - let baseUrl = this.options.getValue('baseUrl'); + let baseUrl = this.options.getValue('baseUrl'); - if (!baseUrl.startsWith('/')) { - baseUrl = `/${baseUrl}`; - } + if (!baseUrl.startsWith('/')) { + baseUrl = `/${baseUrl}`; + } - if (!baseUrl.endsWith('/')) { - baseUrl = `${baseUrl}/`; - } + if (!baseUrl.endsWith('/')) { + baseUrl = `${baseUrl}/`; + } - let constructedUrl = typeof baseUrl === 'string' ? baseUrl : ''; - constructedUrl += segments.length > 0 ? `${segments.join('/')}/` : ''; - constructedUrl += slug(filePath.name); - constructedUrl += '/'; - constructedUrl += anchor && anchor.length > 0 ? `#${anchor}` : ''; + let constructedUrl = typeof baseUrl === 'string' ? baseUrl : ''; + constructedUrl += segments.length > 0 ? `${segments.join('/')}/` : ''; + constructedUrl += slug(filePath.name); + constructedUrl += '/'; + constructedUrl += anchor && anchor.length > 0 ? `#${anchor}` : ''; - return constructedUrl; - }; + return constructedUrl; + }; } -generator() \ No newline at end of file +generator(); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 724d01bf0..16b71b2da 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -28,6 +28,12 @@ importers: astro-feelback: specifier: ^0.3.4 version: 0.3.4 + prettier: + specifier: ^3.0.1 + version: 3.0.1 + prettier-plugin-astro: + specifier: ^0.11.0 + version: 0.11.0 rehype-autolink-headings: specifier: ^6.1.1 version: 6.1.1 @@ -3666,6 +3672,15 @@ packages: which-pm: 2.0.0 dev: false + /prettier-plugin-astro@0.11.0: + resolution: {integrity: sha512-rl2hJ4Kty/aEfGjk3i4JS+bpng9MjgvwqLRNzeb9NqYhqKoWNwOR39cIJXFjU1vR3zYOPnwWNRMelKb0orunYA==} + engines: {node: ^14.15.0 || >=16.0.0, pnpm: '>=7.14.0'} + dependencies: + '@astrojs/compiler': 1.8.0 + prettier: 3.0.1 + sass-formatter: 0.7.6 + dev: false + /prettier-plugin-astro@0.9.1: resolution: {integrity: sha512-pYZXSbdq0eElvzoIMArzv1SBn1NUXzopjlcnt6Ql8VW32PjC12NovwBjXJ6rh8qQLi7vF8jNqAbraKW03UPfag==} engines: {node: ^14.15.0 || >=16.0.0, pnpm: '>=7.14.0'} @@ -3682,6 +3697,12 @@ packages: hasBin: true dev: false + /prettier@3.0.1: + resolution: {integrity: sha512-fcOWSnnpCrovBsmFZIGIy9UqK2FaI7Hqax+DIO0A9UxeVoY4iweyaFjS5TavZN97Hfehph0nhsZnjlVKzEQSrQ==} + engines: {node: '>=14'} + hasBin: true + dev: false + /prismjs@1.29.0: resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==} engines: {node: '>=6'} diff --git a/src/components/Feedback.astro b/src/components/Feedback.astro index 9c2a8b261..56771a908 100644 --- a/src/components/Feedback.astro +++ b/src/components/Feedback.astro @@ -1,14 +1,14 @@ --- -import FeelbackReaction from "astro-feelback/components/FeelbackReaction.astro"; -import "astro-feelback/styles/feelback.css"; +import FeelbackReaction from 'astro-feelback/components/FeelbackReaction.astro'; +import 'astro-feelback/styles/feelback.css'; // Waiting for https://discord.com/channels/830184174198718474/1134090586052378624 to be build out to dynamically insert into the layout for every page -const CONTENT_SET_ID = "54faa8e2-cd0d-4997-9a3c-d9fed28f358a" +const CONTENT_SET_ID = '54faa8e2-cd0d-4997-9a3c-d9fed28f358a'; --- \ No newline at end of file + contentSetId={CONTENT_SET_ID} + key={Astro.url.pathname} + layout="list" + preset="feeling" +/> diff --git a/src/components/Stub.astro b/src/components/Stub.astro index 398dce479..22b90ea15 100644 --- a/src/components/Stub.astro +++ b/src/components/Stub.astro @@ -5,19 +5,19 @@ const baseUrl = 'https://github.com/tauri-apps/tauri-docs/tree/starlight'; --- -

- This page is a stub and is waiting for contributions. Get involved by - visiting us on GitHub or joining us on Discord. -

+

+ This page is a stub and is waiting for contributions. Get involved by + visiting us on GitHub or joining us on Discord. +

- { - Astro.slots.has('default') && ( - <> -
Here are some ideas to get you started:
- - - ) - } + { + Astro.slots.has('default') && ( + <> +
Here are some ideas to get you started:
+ + + ) + } diff --git a/src/content/config.ts b/src/content/config.ts index 02ea2ac07..9df91b604 100644 --- a/src/content/config.ts +++ b/src/content/config.ts @@ -2,6 +2,6 @@ import { defineCollection } from 'astro:content'; import { docsSchema, i18nSchema } from '@astrojs/starlight/schema'; export const collections = { - docs: defineCollection({ schema: docsSchema() }), - i18n: defineCollection({ type: 'data', schema: i18nSchema() }), + docs: defineCollection({ schema: docsSchema() }), + i18n: defineCollection({ type: 'data', schema: i18nSchema() }), }; diff --git a/src/content/docs/2/guide/create/mobile.mdx b/src/content/docs/2/guide/create/mobile.mdx index 6bb80ec91..84b112e00 100644 --- a/src/content/docs/2/guide/create/mobile.mdx +++ b/src/content/docs/2/guide/create/mobile.mdx @@ -117,23 +117,23 @@ import { internalIpV4 } from 'internal-ip'; // https://vitejs.dev/config/ export default defineConfig(async () => { - const host = await internalIpV4(); + const host = await internalIpV4(); - /** @type {import('vite').UserConfig} */ - const config = { - server: { - host: '0.0.0.0', // listen on all addresses - port: 5173, - strictPort: true, - hmr: { - protocol: 'ws', - host, - port: 5183, - }, - }, - }; + /** @type {import('vite').UserConfig} */ + const config = { + server: { + host: '0.0.0.0', // listen on all addresses + port: 5173, + strictPort: true, + hmr: { + protocol: 'ws', + host, + port: 5183, + }, + }, + }; - return config; + return config; }); ``` @@ -144,25 +144,25 @@ For Next.js, you need to configure the [assetPrefix] to use the internal IP so t ```typescript title=next.config.js const isProd = process.env.NODE_ENV === 'production'; module.exports = async (phase, { defaultConfig }) => { - let internalHost = null; - if (!isProd) { - const { internalIpV4 } = await import('internal-ip'); - internalHost = await internalIpV4(); - } - /** - * @type {import('next').NextConfig} - */ - const nextConfig = { - reactStrictMode: true, - swcMinify: true, - // Note: This experimental feature is required to use NextJS Image in SSG mode. - // See https://nextjs.org/docs/messages/export-image-api for different workarounds. - images: { - unoptimized: true, - }, - assetPrefix: isProd ? null : `http://${internalHost}:3000`, - }; - return nextConfig; + let internalHost = null; + if (!isProd) { + const { internalIpV4 } = await import('internal-ip'); + internalHost = await internalIpV4(); + } + /** + * @type {import('next').NextConfig} + */ + const nextConfig = { + reactStrictMode: true, + swcMinify: true, + // Note: This experimental feature is required to use NextJS Image in SSG mode. + // See https://nextjs.org/docs/messages/export-image-api for different workarounds. + images: { + unoptimized: true, + }, + assetPrefix: isProd ? null : `http://${internalHost}:3000`, + }; + return nextConfig; }; ``` @@ -175,9 +175,9 @@ Webpack has a built-in option to use the local IP address as the host for the de ```typescript title=webpack.config.js export default { - devServer: { - host: 'local-ipv4', - }, + devServer: { + host: 'local-ipv4', + }, }; ``` diff --git a/src/content/docs/2/guide/index.mdx b/src/content/docs/2/guide/index.mdx index 92a8ba1fb..734ffff9b 100644 --- a/src/content/docs/2/guide/index.mdx +++ b/src/content/docs/2/guide/index.mdx @@ -12,8 +12,8 @@ This documentation is for the prereleased version of Tauri 2.0 and is subject to ::: - Get ready to make a Tauri project by installing the - [prerequisites](/2/guide/prerequisites). + Get ready to make a Tauri project by installing the + [prerequisites](/2/guide/prerequisites). diff --git a/src/content/docs/index.mdx b/src/content/docs/index.mdx index 8834d1bd1..33b3f2d31 100644 --- a/src/content/docs/index.mdx +++ b/src/content/docs/index.mdx @@ -23,35 +23,35 @@ hero: import { Card, CardGrid } from '@astrojs/starlight/components';
- -
-
+ +
+
- - Bring your existing web stack to Tauri or start that new dream project. - Tauri supports any frontend framework so you don't need to change your - stack. - - - Build your app for Linux, macOS, Windows, Android and iOS - all from a - single codebase. - - - Write your frontend in JavaScript, application logic in Rust, and integrate - deep into the system with Swift and Kotlin. - - - Front-of-mind for the Tauri Team driving our highest priorities and biggest - innovations. - - - By using the OS's native web renderer, the size of a Tauri app can be less - than 600KB. - - - With performance and security at the center, Rust is the language for the - next generation of apps. - + + Bring your existing web stack to Tauri or start that new dream project. + Tauri supports any frontend framework so you don't need to change your + stack. + + + Build your app for Linux, macOS, Windows, Android and iOS - all from a + single codebase. + + + Write your frontend in JavaScript, application logic in Rust, and integrate + deep into the system with Swift and Kotlin. + + + Front-of-mind for the Tauri Team driving our highest priorities and biggest + innovations. + + + By using the OS's native web renderer, the size of a Tauri app can be less + than 600KB. + + + With performance and security at the center, Rust is the language for the + next generation of apps. + diff --git a/src/plugins/configGenerator.ts b/src/plugins/configGenerator.ts index 625fe65a4..fb0e8583e 100644 --- a/src/plugins/configGenerator.ts +++ b/src/plugins/configGenerator.ts @@ -1,502 +1,470 @@ import fs from 'node:fs'; export default async function configGenerator() { - if (fs.existsSync('packages/tauri/tooling/api/node_modules')) { - const schemaPath = 'packages/tauri/core/tauri-config-schema/schema.json'; - const schemaString = fs - .readFileSync(schemaPath) - .toString() - // Fixes any angle brackets that aren't escaped propertly - .replaceAll('(?', '>'); - const schema = JSON.parse(schemaString); - const targetPath = 'src/content/docs/2/reference/config.md'; - const nullMarkdown = '_null_'; + if (fs.existsSync('packages/tauri/tooling/api/node_modules')) { + const schemaPath = 'packages/tauri/core/tauri-config-schema/schema.json'; + const schemaString = fs + .readFileSync(schemaPath) + .toString() + // Fixes any angle brackets that aren't escaped propertly + .replaceAll('(?', '>'); + const schema = JSON.parse(schemaString); + const targetPath = 'src/content/docs/2/reference/config.md'; + const nullMarkdown = '_null_'; - const header = `--- + const header = `--- title: Tauri Configuration --- `; - const builtDefinitions = []; + const builtDefinitions = []; - function buildObject(key, value, headerLevel) { - let out = []; - headerLevel = Math.min(headerLevel, 6); + function buildObject(key, value, headerLevel) { + let out = []; + headerLevel = Math.min(headerLevel, 6); - var headerTitle = value.title ? 'Configuration' : key; + var headerTitle = value.title ? 'Configuration' : key; - var header = `${'#'.repeat(headerLevel)} ${headerTitle}\n`; + var header = `${'#'.repeat(headerLevel)} ${headerTitle}\n`; - if (headerLevel === 1) { - headerLevel = 2; - } + if (headerLevel === 1) { + headerLevel = 2; + } - out.push(header); - out.push(`${descriptionConstructor(value.description)}\n`); + out.push(header); + out.push(`${descriptionConstructor(value.description)}\n`); - out.push(`${longFormTypeConstructor(key, value, headerLevel)}\n`); - out = out.concat(buildProperties(headerTitle, value, headerLevel)); + out.push(`${longFormTypeConstructor(key, value, headerLevel)}\n`); + out = out.concat(buildProperties(headerTitle, value, headerLevel)); - out = out.concat(inspectRef(value, headerLevel + 1)); + out = out.concat(inspectRef(value, headerLevel + 1)); - return out; - } + return out; + } - function buildDef(name, headerLevel) { - const def = name.replace('#/definitions/', ''); - if (!builtDefinitions.includes(def)) { - builtDefinitions.push(def); - const obj = schema.definitions[def]; - return buildObject(def, obj, headerLevel); - } - return []; - } + function buildDef(name, headerLevel) { + const def = name.replace('#/definitions/', ''); + if (!builtDefinitions.includes(def)) { + builtDefinitions.push(def); + const obj = schema.definitions[def]; + return buildObject(def, obj, headerLevel); + } + return []; + } - function inspectRef(object, headerLevel) { - let out = []; - - if (object.$ref) { - out = out.concat(buildDef(object.$ref, headerLevel)); - } - - if (object.additionalProperties && object.additionalProperties.$ref) { - out = out.concat( - buildDef(object.additionalProperties.$ref, headerLevel) - ); - } - - if (object.items && object.items.$ref) { - out = out.concat(buildDef(object.items.$ref, headerLevel)); - } - - for (const opt of object.allOf || []) { - out = out.concat(inspectRef(opt, headerLevel)); - } - - for (const opt of object.anyOf || []) { - out = out.concat(inspectRef(opt, headerLevel)); - } - - return out; - } - - function buildProperties(parentName, object, headerLevel) { - const out = []; - if (!object.properties) return out; - - const required = object.required || []; - - // Build table header - out.push('| Name | Type | Default | Description |'); - out.push('| ---- | ---- | ------- | ----------- |'); - - let definitions = []; - - // Populate table - Object.entries(object.properties).forEach(([key, value]) => { - if (key == '$schema') return; - - let propertyType = typeConstructor(value, true); - let propertyDefault = defaultConstructor(value); - - if (required.includes(key)) { - propertyType += ' (required)'; - if (propertyDefault === nullMarkdown) { - propertyDefault = ''; - } - } - - const url = `${parentName.toLowerCase()}.${key.toLowerCase()}`; - const name = `
\`${key}\`
`; - out.push( - `| ${name} | ${propertyType} | ${propertyDefault} | ${descriptionConstructor( - value.description, - true - )} |` - ); - - definitions = definitions.concat(inspectRef(value, headerLevel + 1)); - }); - - out.push('\n'); - - return out.concat(definitions); - } - - function descriptionConstructor(description, fixNewlines = false) { - if (!description) return; - - // Remove links to current page - description = description.replaceAll( - /\n\nSee more: https:\/\/tauri\.app\/v[0-9]\/api\/config.*$/g, - '' - ); - - // fix Rust doc style links - description = description.replaceAll(/\[`Self::(\S+)`\]/g, '`$1`'); - - // Fix bullet points not being on a newline - description = description.replaceAll(' - ', '\n- '); - - // Parse any json code blocks - if (description.includes('```json ')) { - let newDescription = ''; - const s = description.split('```'); - - for (const text of s) { - if (text.startsWith('json')) { - const description = text.match(/([^{]+)/)[0]; - const json = JSON.stringify( - JSON.parse(text.replace(description, '')), - null, - 2 - ); - newDescription += `${description}\n${json}\n`; - } else { - newDescription += text + '```'; - } - } - description = newDescription; - } - - const referenceStyleLinksRegex = /(\[[A-Za-z0-9 ]+\]): (.+)/g; - const referenceStyleLinksMatches = - referenceStyleLinksRegex.exec(description); - if (referenceStyleLinksMatches) { - let link = referenceStyleLinksMatches[2]; - // strip `<` and `>` from `<$url>` - if (link.startsWith('<')) { - link = link.substring(1, link.length - 1); - } - description = description - .replace(referenceStyleLinksMatches[0], '') - .replace( - referenceStyleLinksMatches[1], - `${referenceStyleLinksMatches[1]}(${link})` - ) - .trim(); - } - - // Fix any embedded new lines - if (fixNewlines) { - description = description.replaceAll('\n', '
'); - } - - const markdownLinkRegex = /\[([^\[]+)\]\((.*)\)/gm; - const markdownLinkMatches = markdownLinkRegex.exec(description); - - if (markdownLinkMatches) { - const url = markdownLinkMatches[2]; - if (!url.startsWith('http')) { - description = description.replace( - url, - `#${url.toLowerCase().replaceAll('_', '')}` - ); - } - } - return description; - } - - function typeConstructor(object, describeObject = false) { - const canBeNull = - (object.type && object.type.includes('null')) || - (object.anyOf && object.anyOf.some((item) => item.type === 'null')); - - if (object.$ref) { - return refLinkConstructor(object.$ref, canBeNull); - } - - if (object.additionalProperties && object.additionalProperties.$ref) { - return refLinkConstructor(object.additionalProperties.$ref, canBeNull); - } - - if (object.items && object.items.$ref) { - return refLinkConstructor(object.items.$ref, canBeNull); - } - - if (object.anyOf) { - // Removes any null values - const items = object.anyOf.filter( - (item) => !(item.type && item.type == 'null') - ); - - if (canBeNull && items.length == 1) { - return `${items.map((t) => typeConstructor(t, describeObject))}?`; - } - - return items - .map((t) => typeConstructor(t, describeObject)) - .join(' \\| '); - } - - if (object.allOf) { - return refLinkConstructor(object.allOf[0].$ref); - } - - if (object.oneOf) { - return object.oneOf - .map((t) => typeConstructor(t, describeObject)) - .join(' | '); - } - - const m = describeObject ? '' : '`'; - - if (object.type) { - var typeString = ''; - - // See what the type is - switch (typeof object.type) { - case 'string': - // See if referencing a different type - switch (object.type) { - case 'string': - typeString = object.enum - ? object.enum.map((e) => `"${e}"`).join(', ') - : `${m}${object.type}${m}`; - break; - case 'number': - case 'integer': - case 'boolean': - typeString = `${m}${object.type}${m}`; - break; - case 'object': - if (describeObject && object.properties) { - typeString = `${m}{`; - const len = Object.keys(object.properties).length; - let i = 0; - for (const prop in object.properties) { - typeString += ` "${prop}": ${typeConstructor( - object.properties[prop], - describeObject - )}`; - i++; - if (i < len) typeString += ','; - } - typeString += ` }${m}`; - } else { - typeString = `${m}${object.type}${m}`; - } - break; - case 'array': - if (object.items) { - if (describeObject) { - typeString = `${typeConstructor( - object.items, - describeObject - )}[]`; - } else { - const type = typeConstructor(object.items, true); - const hasLink = type.includes('(#'); - typeString = hasLink - ? type.replace(/\[`(.*)`\]/, '[`$1[]`]') - : `${m}${type}[]${m}`; - } - break; - } - default: - break; - } - break; - case 'undefined': - typeString = nullMarkdown; - break; - case 'object': - if (Array.isArray(object.type)) { - // Check if it should just be an optional value - if (object.type.length == 2 && object.type.includes('null')) { - typeString = `${m}${object.type.filter( - (item) => item != 'null' - )}${m}?`; - break; - } - } - default: - break; - } - - var additionalProperties = []; - - if (object.format) { - additionalProperties.push(`format: \`${object.format}\``); - } - - if (object.multipleOf) { - additionalProperties.push(`multiple of: \`${object.multipleOf}\``); - } - - if (object.minimum) { - additionalProperties.push(`minimum: \`${object.minimum}\``); - } - - if (object.exclusiveMinimum) { - additionalProperties.push( - `exclusive minimum: \`${object.exclusiveMinimum}\`` - ); - } - - if (object.maximum) { - additionalProperties.push(`maximum: \`${object.maximum}\``); - } - - if (object.exclusiveMaximum) { - additionalProperties.push( - `exclusive maximum: \`${object.exclusiveMaximum}\`` - ); - } - - if (typeString != '') { - if (additionalProperties.length > 0) { - const props = `_(${additionalProperties.join(', ')})_`; - return `${typeString} ${props}`; - } - return typeString; - } - } - - if (object.enum) { - return `${m}${object.enum.map((e) => `"${e}"`).join(', ')}${m}`; - } - - if (Array.isArray(object)) { - if (describeObject) { - const type = []; - for (const obj of object) { - type.push(typeConstructor(obj)); - } - if (type.every((t) => t === type[0])) { - return `${m}${type[0]}${m}`; - } - return `${m}[${type.join(', ')}]${m}`; - } else { - return `${m}array${m}`; - } - } - - console.log('A type was not able to be parsed:', object); - return JSON.stringify(object); - } - - /** prepares a description to be added to a markdown bullet point list */ - function listDescription(description) { - return description.replace('\n\n', '\n\n\t'); - } - - function longFormTypeConstructor(key, object, headerLevel) { - if (object.enum) { - var buffer = []; - buffer.push(`Can be any of the following \`${object.type}\` values:`); - object.enum.forEach((item) => { - buffer.push(`- ${item}`); - }); - return buffer.join('\n'); - } - if (object.anyOf) { - var buffer = []; - buffer.push('Can be any of the following types:\n'); - object.anyOf.forEach((item) => { - var description = ':'; - if (item.description) { - description = `: ${descriptionConstructor(item.description)}`; - } - const hasProperties = 'properties' in item; - let typeDef = typeConstructor(item, hasProperties); - if (hasProperties) { - typeDef = '`' + typeDef + '`'; - } - buffer.push(`- ${typeDef}${listDescription(description)}`); - if (hasProperties) { - buffer.push('\n\t'); - buffer.push( - buildProperties(key, item, headerLevel) - .map((line) => `\t${line}`) - .join('\n') - ); - } - }); - - return buffer.join(`\n`); - } - - if (object.oneOf) { - var buffer = []; - buffer.push('Can be any **ONE** of the following types:\n'); - object.oneOf.forEach((item) => { - var description = ':'; - if (item.description) { - description = `: ${descriptionConstructor(item.description)}`; - } - const hasProperties = 'properties' in item; - let typeDef = typeConstructor(item, hasProperties); - if (hasProperties) { - typeDef = '`' + typeDef + '`'; - } - buffer.push(`- ${typeDef}${listDescription(description)}`); - if ('properties' in item) { - buffer.push('\n\t'); - buffer.push( - buildProperties(key, item, headerLevel) - .map((line) => `\t${line}`) - .join('\n') - ); - } - }); - - return buffer.join(`\n`); - } - - return `Type: ${typeConstructor(object)}`; - } - - function defaultConstructor(object) { - switch (typeof object.default) { - case 'boolean': - case 'number': - return `\`${object.default}\``; - case 'object': - // Check if empty array - if (Array.isArray(object.default) && object.default.length == 0) { - return '[]'; - } - default: - } - - if (object.$ref) { - console.error('Found $ref default:', object.$ref); - } - - if (object.anyOf) { - const link = object.anyOf[0].$ref - .replace('#/definitions/', '') - .toLowerCase(); - return `[view](#${link})`; - } - - if (object.allOf) { - const link = object.allOf[0].$ref - .replace('#/definitions/', '') - .toLowerCase(); - return `[view](#${link})`; - } - - if (object.oneOf) { - console.error('Found oneOf default:', object.oneOf); - } - - return nullMarkdown; - } - - function refLinkConstructor(string, nullable = false) { - const name = string.replace('#/definitions/', ''); - return `[\`${name}\`](#${name.toLowerCase()})${nullable ? '?' : ''}`; - } - - const config = buildObject(null, schema, 1).join('\n'); - fs.writeFileSync(targetPath, `${header}${config}`); - } else { - console.log( - 'Tauri submodule is not initialized, respective core config routes will not be rendered.' - ); - } + function inspectRef(object, headerLevel) { + let out = []; + + if (object.$ref) { + out = out.concat(buildDef(object.$ref, headerLevel)); + } + + if (object.additionalProperties && object.additionalProperties.$ref) { + out = out.concat(buildDef(object.additionalProperties.$ref, headerLevel)); + } + + if (object.items && object.items.$ref) { + out = out.concat(buildDef(object.items.$ref, headerLevel)); + } + + for (const opt of object.allOf || []) { + out = out.concat(inspectRef(opt, headerLevel)); + } + + for (const opt of object.anyOf || []) { + out = out.concat(inspectRef(opt, headerLevel)); + } + + return out; + } + + function buildProperties(parentName, object, headerLevel) { + const out = []; + if (!object.properties) return out; + + const required = object.required || []; + + // Build table header + out.push('| Name | Type | Default | Description |'); + out.push('| ---- | ---- | ------- | ----------- |'); + + let definitions = []; + + // Populate table + Object.entries(object.properties).forEach(([key, value]) => { + if (key == '$schema') return; + + let propertyType = typeConstructor(value, true); + let propertyDefault = defaultConstructor(value); + + if (required.includes(key)) { + propertyType += ' (required)'; + if (propertyDefault === nullMarkdown) { + propertyDefault = ''; + } + } + + const url = `${parentName.toLowerCase()}.${key.toLowerCase()}`; + const name = `
\`${key}\`
`; + out.push( + `| ${name} | ${propertyType} | ${propertyDefault} | ${descriptionConstructor( + value.description, + true + )} |` + ); + + definitions = definitions.concat(inspectRef(value, headerLevel + 1)); + }); + + out.push('\n'); + + return out.concat(definitions); + } + + function descriptionConstructor(description, fixNewlines = false) { + if (!description) return; + + // Remove links to current page + description = description.replaceAll( + /\n\nSee more: https:\/\/tauri\.app\/v[0-9]\/api\/config.*$/g, + '' + ); + + // fix Rust doc style links + description = description.replaceAll(/\[`Self::(\S+)`\]/g, '`$1`'); + + // Fix bullet points not being on a newline + description = description.replaceAll(' - ', '\n- '); + + // Parse any json code blocks + if (description.includes('```json ')) { + let newDescription = ''; + const s = description.split('```'); + + for (const text of s) { + if (text.startsWith('json')) { + const description = text.match(/([^{]+)/)[0]; + const json = JSON.stringify(JSON.parse(text.replace(description, '')), null, 2); + newDescription += `${description}\n${json}\n`; + } else { + newDescription += text + '```'; + } + } + description = newDescription; + } + + const referenceStyleLinksRegex = /(\[[A-Za-z0-9 ]+\]): (.+)/g; + const referenceStyleLinksMatches = referenceStyleLinksRegex.exec(description); + if (referenceStyleLinksMatches) { + let link = referenceStyleLinksMatches[2]; + // strip `<` and `>` from `<$url>` + if (link.startsWith('<')) { + link = link.substring(1, link.length - 1); + } + description = description + .replace(referenceStyleLinksMatches[0], '') + .replace(referenceStyleLinksMatches[1], `${referenceStyleLinksMatches[1]}(${link})`) + .trim(); + } + + // Fix any embedded new lines + if (fixNewlines) { + description = description.replaceAll('\n', '
'); + } + + const markdownLinkRegex = /\[([^\[]+)\]\((.*)\)/gm; + const markdownLinkMatches = markdownLinkRegex.exec(description); + + if (markdownLinkMatches) { + const url = markdownLinkMatches[2]; + if (!url.startsWith('http')) { + description = description.replace(url, `#${url.toLowerCase().replaceAll('_', '')}`); + } + } + return description; + } + + function typeConstructor(object, describeObject = false) { + const canBeNull = + (object.type && object.type.includes('null')) || + (object.anyOf && object.anyOf.some((item) => item.type === 'null')); + + if (object.$ref) { + return refLinkConstructor(object.$ref, canBeNull); + } + + if (object.additionalProperties && object.additionalProperties.$ref) { + return refLinkConstructor(object.additionalProperties.$ref, canBeNull); + } + + if (object.items && object.items.$ref) { + return refLinkConstructor(object.items.$ref, canBeNull); + } + + if (object.anyOf) { + // Removes any null values + const items = object.anyOf.filter((item) => !(item.type && item.type == 'null')); + + if (canBeNull && items.length == 1) { + return `${items.map((t) => typeConstructor(t, describeObject))}?`; + } + + return items.map((t) => typeConstructor(t, describeObject)).join(' \\| '); + } + + if (object.allOf) { + return refLinkConstructor(object.allOf[0].$ref); + } + + if (object.oneOf) { + return object.oneOf.map((t) => typeConstructor(t, describeObject)).join(' | '); + } + + const m = describeObject ? '' : '`'; + + if (object.type) { + var typeString = ''; + + // See what the type is + switch (typeof object.type) { + case 'string': + // See if referencing a different type + switch (object.type) { + case 'string': + typeString = object.enum + ? object.enum.map((e) => `"${e}"`).join(', ') + : `${m}${object.type}${m}`; + break; + case 'number': + case 'integer': + case 'boolean': + typeString = `${m}${object.type}${m}`; + break; + case 'object': + if (describeObject && object.properties) { + typeString = `${m}{`; + const len = Object.keys(object.properties).length; + let i = 0; + for (const prop in object.properties) { + typeString += ` "${prop}": ${typeConstructor( + object.properties[prop], + describeObject + )}`; + i++; + if (i < len) typeString += ','; + } + typeString += ` }${m}`; + } else { + typeString = `${m}${object.type}${m}`; + } + break; + case 'array': + if (object.items) { + if (describeObject) { + typeString = `${typeConstructor(object.items, describeObject)}[]`; + } else { + const type = typeConstructor(object.items, true); + const hasLink = type.includes('(#'); + typeString = hasLink + ? type.replace(/\[`(.*)`\]/, '[`$1[]`]') + : `${m}${type}[]${m}`; + } + break; + } + default: + break; + } + break; + case 'undefined': + typeString = nullMarkdown; + break; + case 'object': + if (Array.isArray(object.type)) { + // Check if it should just be an optional value + if (object.type.length == 2 && object.type.includes('null')) { + typeString = `${m}${object.type.filter((item) => item != 'null')}${m}?`; + break; + } + } + default: + break; + } + + var additionalProperties = []; + + if (object.format) { + additionalProperties.push(`format: \`${object.format}\``); + } + + if (object.multipleOf) { + additionalProperties.push(`multiple of: \`${object.multipleOf}\``); + } + + if (object.minimum) { + additionalProperties.push(`minimum: \`${object.minimum}\``); + } + + if (object.exclusiveMinimum) { + additionalProperties.push(`exclusive minimum: \`${object.exclusiveMinimum}\``); + } + + if (object.maximum) { + additionalProperties.push(`maximum: \`${object.maximum}\``); + } + + if (object.exclusiveMaximum) { + additionalProperties.push(`exclusive maximum: \`${object.exclusiveMaximum}\``); + } + + if (typeString != '') { + if (additionalProperties.length > 0) { + const props = `_(${additionalProperties.join(', ')})_`; + return `${typeString} ${props}`; + } + return typeString; + } + } + + if (object.enum) { + return `${m}${object.enum.map((e) => `"${e}"`).join(', ')}${m}`; + } + + if (Array.isArray(object)) { + if (describeObject) { + const type = []; + for (const obj of object) { + type.push(typeConstructor(obj)); + } + if (type.every((t) => t === type[0])) { + return `${m}${type[0]}${m}`; + } + return `${m}[${type.join(', ')}]${m}`; + } else { + return `${m}array${m}`; + } + } + + console.log('A type was not able to be parsed:', object); + return JSON.stringify(object); + } + + /** prepares a description to be added to a markdown bullet point list */ + function listDescription(description) { + return description.replace('\n\n', '\n\n\t'); + } + + function longFormTypeConstructor(key, object, headerLevel) { + if (object.enum) { + var buffer = []; + buffer.push(`Can be any of the following \`${object.type}\` values:`); + object.enum.forEach((item) => { + buffer.push(`- ${item}`); + }); + return buffer.join('\n'); + } + if (object.anyOf) { + var buffer = []; + buffer.push('Can be any of the following types:\n'); + object.anyOf.forEach((item) => { + var description = ':'; + if (item.description) { + description = `: ${descriptionConstructor(item.description)}`; + } + const hasProperties = 'properties' in item; + let typeDef = typeConstructor(item, hasProperties); + if (hasProperties) { + typeDef = '`' + typeDef + '`'; + } + buffer.push(`- ${typeDef}${listDescription(description)}`); + if (hasProperties) { + buffer.push('\n\t'); + buffer.push( + buildProperties(key, item, headerLevel) + .map((line) => `\t${line}`) + .join('\n') + ); + } + }); + + return buffer.join(`\n`); + } + + if (object.oneOf) { + var buffer = []; + buffer.push('Can be any **ONE** of the following types:\n'); + object.oneOf.forEach((item) => { + var description = ':'; + if (item.description) { + description = `: ${descriptionConstructor(item.description)}`; + } + const hasProperties = 'properties' in item; + let typeDef = typeConstructor(item, hasProperties); + if (hasProperties) { + typeDef = '`' + typeDef + '`'; + } + buffer.push(`- ${typeDef}${listDescription(description)}`); + if ('properties' in item) { + buffer.push('\n\t'); + buffer.push( + buildProperties(key, item, headerLevel) + .map((line) => `\t${line}`) + .join('\n') + ); + } + }); + + return buffer.join(`\n`); + } + + return `Type: ${typeConstructor(object)}`; + } + + function defaultConstructor(object) { + switch (typeof object.default) { + case 'boolean': + case 'number': + return `\`${object.default}\``; + case 'object': + // Check if empty array + if (Array.isArray(object.default) && object.default.length == 0) { + return '[]'; + } + default: + } + + if (object.$ref) { + console.error('Found $ref default:', object.$ref); + } + + if (object.anyOf) { + const link = object.anyOf[0].$ref.replace('#/definitions/', '').toLowerCase(); + return `[view](#${link})`; + } + + if (object.allOf) { + const link = object.allOf[0].$ref.replace('#/definitions/', '').toLowerCase(); + return `[view](#${link})`; + } + + if (object.oneOf) { + console.error('Found oneOf default:', object.oneOf); + } + + return nullMarkdown; + } + + function refLinkConstructor(string, nullable = false) { + const name = string.replace('#/definitions/', ''); + return `[\`${name}\`](#${name.toLowerCase()})${nullable ? '?' : ''}`; + } + + const config = buildObject(null, schema, 1).join('\n'); + fs.writeFileSync(targetPath, `${header}${config}`); + } else { + console.log( + 'Tauri submodule is not initialized, respective core config routes will not be rendered.' + ); + } } diff --git a/src/styles/custom.css b/src/styles/custom.css index efd39be89..f69a7bcb0 100644 --- a/src/styles/custom.css +++ b/src/styles/custom.css @@ -1,224 +1,208 @@ :root { - --sl-color-white: hsl(0, 0%, 100%); - --sl-color-gray-1: hsl(231, 23%, 94%); - --sl-color-gray-2: hsl(228, 8%, 77%); - --sl-color-gray-3: hsl(221, 8%, 56%); - --sl-color-gray-4: hsl(225, 9%, 36%); - --sl-color-gray-5: hsl(222, 11%, 23%); - --sl-color-gray-6: hsl(180, 2%, 10%); - --sl-color-black: hsl(0, 0%, 7%); + --sl-color-white: hsl(0, 0%, 100%); + --sl-color-gray-1: hsl(231, 23%, 94%); + --sl-color-gray-2: hsl(228, 8%, 77%); + --sl-color-gray-3: hsl(221, 8%, 56%); + --sl-color-gray-4: hsl(225, 9%, 36%); + --sl-color-gray-5: hsl(222, 11%, 23%); + --sl-color-gray-6: hsl(180, 2%, 10%); + --sl-color-black: hsl(0, 0%, 7%); - --sl-hue-orange: 41; - --sl-color-orange-low: hsl(var(--sl-hue-orange), 39%, 22%); - --sl-color-orange: hsl(var(--sl-hue-orange), 82%, 63%); - --sl-color-orange-high: hsl(var(--sl-hue-orange), 82%, 87%); - --sl-hue-green: 101; - --sl-color-green-low: hsl(var(--sl-hue-green), 39%, 22%); - --sl-color-green: hsl(var(--sl-hue-green), 82%, 63%); - --sl-color-green-high: hsl(var(--sl-hue-green), 82%, 80%); - --sl-hue-blue: 234; - --sl-color-blue-low: hsl(var(--sl-hue-blue), 54%, 20%); - --sl-color-blue: hsl(var(--sl-hue-blue), 100%, 60%); - --sl-color-blue-high: hsl(var(--sl-hue-blue), 100%, 87%); - --sl-hue-purple: 281; - --sl-color-purple-low: hsl(var(--sl-hue-purple), 39%, 22%); - --sl-color-purple: hsl(var(--sl-hue-purple), 82%, 63%); - --sl-color-purple-high: hsl(var(--sl-hue-purple), 82%, 89%); - --sl-hue-red: 339; - --sl-color-red-low: hsl(var(--sl-hue-red), 39%, 22%); - --sl-color-red: hsl(var(--sl-hue-red), 82%, 63%); - --sl-color-red-high: hsl(var(--sl-hue-red), 82%, 87%); + --sl-hue-orange: 41; + --sl-color-orange-low: hsl(var(--sl-hue-orange), 39%, 22%); + --sl-color-orange: hsl(var(--sl-hue-orange), 82%, 63%); + --sl-color-orange-high: hsl(var(--sl-hue-orange), 82%, 87%); + --sl-hue-green: 101; + --sl-color-green-low: hsl(var(--sl-hue-green), 39%, 22%); + --sl-color-green: hsl(var(--sl-hue-green), 82%, 63%); + --sl-color-green-high: hsl(var(--sl-hue-green), 82%, 80%); + --sl-hue-blue: 234; + --sl-color-blue-low: hsl(var(--sl-hue-blue), 54%, 20%); + --sl-color-blue: hsl(var(--sl-hue-blue), 100%, 60%); + --sl-color-blue-high: hsl(var(--sl-hue-blue), 100%, 87%); + --sl-hue-purple: 281; + --sl-color-purple-low: hsl(var(--sl-hue-purple), 39%, 22%); + --sl-color-purple: hsl(var(--sl-hue-purple), 82%, 63%); + --sl-color-purple-high: hsl(var(--sl-hue-purple), 82%, 89%); + --sl-hue-red: 339; + --sl-color-red-low: hsl(var(--sl-hue-red), 39%, 22%); + --sl-color-red: hsl(var(--sl-hue-red), 82%, 63%); + --sl-color-red-high: hsl(var(--sl-hue-red), 82%, 87%); - --sl-hue-accent: var(--sl-hue-blue); - --sl-color-accent-low: hsl(var(--sl-hue-accent), 54%, 20%); - --sl-color-accent: hsl(var(--sl-hue-accent), 100%, 60%); - --sl-color-accent-high: hsl(var(--sl-hue-accent), 100%, 87%); + --sl-hue-accent: var(--sl-hue-blue); + --sl-color-accent-low: hsl(var(--sl-hue-accent), 54%, 20%); + --sl-color-accent: hsl(var(--sl-hue-accent), 100%, 60%); + --sl-color-accent-high: hsl(var(--sl-hue-accent), 100%, 87%); - --sl-color-text: var(--sl-color-gray-2); - --sl-color-text-accent: var(--sl-color-accent-high); - --sl-color-text-invert: var(--sl-color-accent-low); - --sl-color-bg: var(--sl-color-black); - --sl-color-bg-nav: var(--sl-color-gray-6); - --sl-color-bg-sidebar: var(--sl-color-gray-6); - --sl-color-bg-inline-code: var(--sl-color-gray-5); - --sl-color-hairline-light: var(--sl-color-gray-5); - --sl-color-hairline: var(--sl-color-gray-6); - --sl-color-hairline-shade: var(--sl-color-black); + --sl-color-text: var(--sl-color-gray-2); + --sl-color-text-accent: var(--sl-color-accent-high); + --sl-color-text-invert: var(--sl-color-accent-low); + --sl-color-bg: var(--sl-color-black); + --sl-color-bg-nav: var(--sl-color-gray-6); + --sl-color-bg-sidebar: var(--sl-color-gray-6); + --sl-color-bg-inline-code: var(--sl-color-gray-5); + --sl-color-hairline-light: var(--sl-color-gray-5); + --sl-color-hairline: var(--sl-color-gray-6); + --sl-color-hairline-shade: var(--sl-color-black); - --sl-hue-blue: 186; - --sl-hue-orange: 42; + --sl-hue-blue: 186; + --sl-hue-orange: 42; - /* Custom */ - --tauri-transition-speed: 200ms; + /* Custom */ + --tauri-transition-speed: 200ms; } :root[data-theme='light'] { - --sl-color-white: hsl(0, 0%, 100%); - --sl-color-gray-1: hsl(231, 23%, 94%); - --sl-color-gray-2: hsl(228, 8%, 77%); - --sl-color-gray-3: hsl(221, 8%, 56%); - --sl-color-gray-4: hsl(225, 9%, 36%); - --sl-color-gray-5: hsl(222, 11%, 23%); - --sl-color-gray-6: hsl(180, 2%, 10%); - --sl-color-black: hsl(0, 0%, 7%); + --sl-color-white: hsl(0, 0%, 100%); + --sl-color-gray-1: hsl(231, 23%, 94%); + --sl-color-gray-2: hsl(228, 8%, 77%); + --sl-color-gray-3: hsl(221, 8%, 56%); + --sl-color-gray-4: hsl(225, 9%, 36%); + --sl-color-gray-5: hsl(222, 11%, 23%); + --sl-color-gray-6: hsl(180, 2%, 10%); + --sl-color-black: hsl(0, 0%, 7%); - --sl-hue-orange: 41; - --sl-color-orange-low: hsl(var(--sl-hue-orange), 39%, 22%); - --sl-color-orange: hsl(var(--sl-hue-orange), 82%, 63%); - --sl-color-orange-high: hsl(var(--sl-hue-orange), 82%, 87%); - --sl-hue-green: 101; - --sl-color-green-low: hsl(var(--sl-hue-green), 39%, 22%); - --sl-color-green: hsl(var(--sl-hue-green), 82%, 63%); - --sl-color-green-high: hsl(var(--sl-hue-green), 82%, 80%); - --sl-hue-blue: 234; - --sl-color-blue-low: hsl(var(--sl-hue-blue), 54%, 20%); - --sl-color-blue: hsl(var(--sl-hue-blue), 100%, 60%); - --sl-color-blue-high: hsl(var(--sl-hue-blue), 100%, 87%); - --sl-hue-purple: 281; - --sl-color-purple-low: hsl(var(--sl-hue-purple), 39%, 22%); - --sl-color-purple: hsl(var(--sl-hue-purple), 82%, 63%); - --sl-color-purple-high: hsl(var(--sl-hue-purple), 82%, 89%); - --sl-hue-red: 339; - --sl-color-red-low: hsl(var(--sl-hue-red), 39%, 22%); - --sl-color-red: hsl(var(--sl-hue-red), 82%, 63%); - --sl-color-red-high: hsl(var(--sl-hue-red), 82%, 87%); + --sl-hue-orange: 41; + --sl-color-orange-low: hsl(var(--sl-hue-orange), 39%, 22%); + --sl-color-orange: hsl(var(--sl-hue-orange), 82%, 63%); + --sl-color-orange-high: hsl(var(--sl-hue-orange), 82%, 87%); + --sl-hue-green: 101; + --sl-color-green-low: hsl(var(--sl-hue-green), 39%, 22%); + --sl-color-green: hsl(var(--sl-hue-green), 82%, 63%); + --sl-color-green-high: hsl(var(--sl-hue-green), 82%, 80%); + --sl-hue-blue: 234; + --sl-color-blue-low: hsl(var(--sl-hue-blue), 54%, 20%); + --sl-color-blue: hsl(var(--sl-hue-blue), 100%, 60%); + --sl-color-blue-high: hsl(var(--sl-hue-blue), 100%, 87%); + --sl-hue-purple: 281; + --sl-color-purple-low: hsl(var(--sl-hue-purple), 39%, 22%); + --sl-color-purple: hsl(var(--sl-hue-purple), 82%, 63%); + --sl-color-purple-high: hsl(var(--sl-hue-purple), 82%, 89%); + --sl-hue-red: 339; + --sl-color-red-low: hsl(var(--sl-hue-red), 39%, 22%); + --sl-color-red: hsl(var(--sl-hue-red), 82%, 63%); + --sl-color-red-high: hsl(var(--sl-hue-red), 82%, 87%); - --sl-hue-accent: var(--sl-hue-blue); - --sl-color-accent-low: hsl(var(--sl-hue-accent), 54%, 20%); - --sl-color-accent: hsl(var(--sl-hue-accent), 100%, 60%); - --sl-color-accent-high: hsl(var(--sl-hue-accent), 100%, 87%); + --sl-hue-accent: var(--sl-hue-blue); + --sl-color-accent-low: hsl(var(--sl-hue-accent), 54%, 20%); + --sl-color-accent: hsl(var(--sl-hue-accent), 100%, 60%); + --sl-color-accent-high: hsl(var(--sl-hue-accent), 100%, 87%); - --sl-color-text: var(--sl-color-gray-2); - --sl-color-text-accent: var(--sl-color-accent-high); - --sl-color-text-invert: var(--sl-color-accent-low); - --sl-color-bg: var(--sl-color-black); - --sl-color-bg-nav: var(--sl-color-gray-6); - --sl-color-bg-sidebar: var(--sl-color-gray-6); - --sl-color-bg-inline-code: var(--sl-color-gray-5); - --sl-color-hairline-light: var(--sl-color-gray-5); - --sl-color-hairline: var(--sl-color-gray-6); - --sl-color-hairline-shade: var(--sl-color-black); + --sl-color-text: var(--sl-color-gray-2); + --sl-color-text-accent: var(--sl-color-accent-high); + --sl-color-text-invert: var(--sl-color-accent-low); + --sl-color-bg: var(--sl-color-black); + --sl-color-bg-nav: var(--sl-color-gray-6); + --sl-color-bg-sidebar: var(--sl-color-gray-6); + --sl-color-bg-inline-code: var(--sl-color-gray-5); + --sl-color-hairline-light: var(--sl-color-gray-5); + --sl-color-hairline: var(--sl-color-gray-6); + --sl-color-hairline-shade: var(--sl-color-black); - --sl-hue-blue: 186; - --sl-hue-orange: 42; + --sl-hue-blue: 186; + --sl-hue-orange: 42; } .content details { - padding: 0 1rem; + padding: 0 1rem; } .content details[open] { - background-color: var(--sl-color-gray-6); - padding-bottom: rem; + background-color: var(--sl-color-gray-6); + padding-bottom: rem; } .content summary { - cursor: pointer; - padding: 1rem 0; + cursor: pointer; + padding: 1rem 0; } /* Heading link styling */ .heading-link::after { - content: '#'; - padding-inline-start: 0.25em; - opacity: 0; - transition: var(--tauri-transition-speed); + content: '#'; + padding-inline-start: 0.25em; + opacity: 0; + transition: var(--tauri-transition-speed); } .heading-link:hover::after { - color: var(--sl-color-text-accent); - opacity: 1; + color: var(--sl-color-text-accent); + opacity: 1; } .heading-link { - text-decoration: none; - color: var(--sl-color-white) !important; + text-decoration: none; + color: var(--sl-color-white) !important; } .hero-bg { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - display: block; - z-index: -1; - opacity: 0.7; - overflow: hidden; - background: linear-gradient( - -90deg, - rgba(192, 192, 192, 0.2) 1px, - transparent 1px - ), - linear-gradient(rgba(192, 192, 192, 0.2) 1px, transparent 1px), - linear-gradient(-90deg, rgba(192, 192, 192, 0.1) 1px, transparent 1px), - linear-gradient(rgba(192, 192, 192, 0.1) 1px, transparent 1px), - linear-gradient( - transparent 6px, - transparent 6px, - transparent 156px, - transparent 156px - ), - linear-gradient(-90deg, rgba(192, 192, 192, 0.1) 1px, transparent 1px), - linear-gradient( - -90deg, - transparent 6px, - transparent 6px, - transparent 156px, - transparent 156px - ), - linear-gradient(rgba(192, 192, 192, 0.1) 1px, transparent 1px), transparent; - background-size: 32px 32px, 32px 32px, 256px 256px, 256px 256px, 256px 256px, - 256px 256px, 256px 256px, 256px 256px; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: block; + z-index: -1; + opacity: 0.7; + overflow: hidden; + background: linear-gradient(-90deg, rgba(192, 192, 192, 0.2) 1px, transparent 1px), + linear-gradient(rgba(192, 192, 192, 0.2) 1px, transparent 1px), + linear-gradient(-90deg, rgba(192, 192, 192, 0.1) 1px, transparent 1px), + linear-gradient(rgba(192, 192, 192, 0.1) 1px, transparent 1px), + linear-gradient(transparent 6px, transparent 6px, transparent 156px, transparent 156px), + linear-gradient(-90deg, rgba(192, 192, 192, 0.1) 1px, transparent 1px), + linear-gradient(-90deg, transparent 6px, transparent 6px, transparent 156px, transparent 156px), + linear-gradient(rgba(192, 192, 192, 0.1) 1px, transparent 1px), transparent; + background-size: + 32px 32px, + 32px 32px, + 256px 256px, + 256px 256px, + 256px 256px, + 256px 256px, + 256px 256px, + 256px 256px; } .hero > img { - opacity: 0.3; - animation: 3s intro; + opacity: 0.3; + animation: 3s intro; } .bg-grad { - position: absolute; - top: -50%; - left: 50%; - width: 150vh; - height: 150vh; - opacity: 0.3; - background: radial-gradient( - circle, - rgba(2, 87, 247, 1) 0%, - rgba(0, 0, 0, 0) 70% - ); - animation: 6s intro; + position: absolute; + top: -50%; + left: 50%; + width: 150vh; + height: 150vh; + opacity: 0.3; + background: radial-gradient(circle, rgba(2, 87, 247, 1) 0%, rgba(0, 0, 0, 0) 70%); + animation: 6s intro; } .bg-grad-red { - position: absolute; - top: 0%; - left: -50%; - width: 150vh; - height: 150vh; - opacity: 0.3; - background: radial-gradient( - circle, - rgb(247, 169, 2) 0%, - rgba(0, 0, 0, 0) 70% - ); - animation: 14s intro; + position: absolute; + top: 0%; + left: -50%; + width: 150vh; + height: 150vh; + opacity: 0.3; + background: radial-gradient(circle, rgb(247, 169, 2) 0%, rgba(0, 0, 0, 0) 70%); + animation: 14s intro; } @keyframes intro { - 0% { - scale: 1.2; - opacity: 0%; - } + 0% { + scale: 1.2; + opacity: 0%; + } - 100% { - } + 100% { + } } @media (prefers-reduced-motion) { - * { - transition: none !important; - } + * { + transition: none !important; + } }