Ctrl K
ComunidadGuías…

docs/rspress.config.ts

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import ogImages from './plugins/ogImages';
import rehypeImageScale from './plugins/rehypeImageScale';
import rehypeImageSize from './plugins/rehypeImageSize';
import rehypeMathPostProcess from './plugins/rehypeMathPostProcess';
import trailingSlashRedirects from './plugins/trailingSlashRedirects';

import path from 'node:path';
import { pluginSass } from '@rsbuild/plugin-sass';
import { defineConfig } from '@rspress/core';
import { pluginRss } from '@rspress/plugin-rss';
import { transformerNotationHighlight } from '@shikijs/transformers';
import rehypeKatex from 'rehype-katex';
import remarkMath from 'remark-math';
import mermaid from 'rspress-plugin-mermaid';
import readingTimePlugin from 'rspress-plugin-reading-time';

const envName = process.env.NODE_ENV ?? 'development';
const branch = process.env.GIT_BRANCH ?? 'main';
const isDevelopment = envName !== 'production';

// rspress-plugin-reading-time attaches a computed reading time to
// pageData.readingTimeData (a reading-time result: { text, minutes, words, ... }).
// Its default behaviour also injects its own component after the first heading,
// but <LedgerMeta> renders the value itself, so we keep only the data hook.
const readingTimeBase = readingTimePlugin();
const readingTimeDataPlugin = {
  name: readingTimeBase.name,
  extendPageData: readingTimeBase.extendPageData,
};

export default defineConfig({
  outDir: process.env.OUTPUT_DIR ?? 'doc_build',
  root: 'src',
  title: 'monetr',
  description:
    'Take control of your finances, paycheck by paycheck, with monetr. Put aside what you need, spend what you want, and confidently manage your money with ease.',
  logo: '/logo.svg',
  icon: '/favicon.ico',
  lang: 'en',
  locales: [{ lang: 'en', label: 'English' }],
  multiVersion: {
    default: 'v1',
    versions: ['v1'],
  },
  globalStyles: path.join(__dirname, 'styles/globals.scss'),
  // The llms build skips markdown.remarkPlugins, so without remarkMath it fails
  // trying to parse the LaTeX in our blog posts as MDX expressions.
  llms: false,
  sitemap: {
    siteUrl: 'https://monetr.app',
  },
  themeConfig: {
    // Docs are dark-mode only: `force-dark` pins dark and hides the appearance
    // toggle. (`darkMode: false` would force *light*, hence the string.)
    darkMode: 'force-dark',
    socialLinks: [
      {
        icon: 'github',
        mode: 'link',
        content: 'https://github.com/monetr/monetr',
      },
      {
        icon: 'discord',
        mode: 'link',
        content: 'https://discord.gg/68wTCXrhuq',
      },
    ],
    footer: {
      message: '',
    },
    editLink: {
      docRepoBaseUrl: `https://github.com/monetr/monetr/blob/${branch}/docs/src`,
    },
    lastUpdated: true,
  },
  markdown: {
    remarkPlugins: [remarkMath],
    rehypePlugins: [
      rehypeKatex,
      rehypeMathPostProcess,
      rehypeImageScale,
      [
        rehypeImageSize,
        {
          publicDir: path.join(__dirname, 'src/public'),
        },
      ],
    ],
    shiki: {
      langs: [
        {
          name: 'math',
          scopeName: 'source.math',
          patterns: [{ match: '.', name: 'text.math' }],
          // Required for some reason?
          repository: {},
        },
      ],
      transformers: [transformerNotationHighlight()],
    },
    link: {
      checkDeadLinks: true,
    },
    image: {
      checkDeadImages: true,
    },
  },
  plugins: [
    pluginRss({
      siteUrl: 'https://monetr.app',
      // Use RSS 2.0; override the default .rss extension to the more familiar .xml so the feed sits at /rss/blog.xml.
      output: {
        type: 'rss',
      },
      feed: {
        id: 'blog',
        test: '/blog/',
        title: 'monetr Blog',
        description: 'Blog posts and announcements from monetr.',
        language: 'en',
        output: {
          filename: 'blog.xml',
        },
        // TODO: channel <link> defaults to siteUrl ("https://monetr.app"); per RSS 2.0 it should point to the HTML page
        // corresponding to the feed ("https://monetr.app/blog"). Override by adding `link` here.
        // TODO: emit <atom:link rel="self">. The feed lib only does so when `feed: '<self URL>'` is set on the channel
        // options. Without it, validators warn with MissingAtomSelfLink.
        // TODO: <guid> currently renders as the relative routePath with isPermaLink="false". Item.link is already the
        // absolute URL, so we could leave guid unset and let the feed lib reuse link as a permalink guid; or set guid
        // explicitly to the absolute URL.
        // Existing blog frontmatter uses `authors` (plural) with { name, github, email } entries. plugin-rss reads
        // `author` (singular), so map it here instead of touching every blog post. Also drop the rendered HTML body
        // from content:encoded: it would otherwise ship root-relative URLs and rspress-specific markup that feed
        // readers can't resolve cleanly. Subscribers see the summary and click through for the full post.
        item(item, page) {
          const next: typeof item = { ...item, content: '' };
          const raw = page.frontmatter?.authors;
          if (!Array.isArray(raw)) {
            return next;
          }
          const authors = raw.flatMap(entry => {
            if (!entry || typeof entry !== 'object') {
              return [];
            }
            const { name, github, email } = entry as {
              name?: unknown;
              github?: unknown;
              email?: unknown;
            };
            if (typeof name !== 'string' || name.length === 0) {
              return [];
            }
            return [
              {
                name,
                // RSS 2.0 requires an email on <author>; fall back to a noreply address so we emit "email (Name)"
                // rather than just the name.
                email: typeof email === 'string' && email.length > 0 ? email : 'noreply@monetr.app',
                link: typeof github === 'string' ? `https://github.com/${github}` : undefined,
              },
            ];
          });
          return authors.length > 0 ? { ...next, author: authors } : next;
        },
      },
    }),
    trailingSlashRedirects({
      siteUrl: 'https://monetr.app',
    }),
    ogImages(),
    readingTimeDataPlugin,
    mermaid({
      // Colors mirror the --mtr-* tokens in styles/globals.scss so diagrams
      // match the MergeDiagram cards. They have to be literal hex: mermaid
      // derives shades from them and can't resolve CSS variables, and its
      // inline styles are id-scoped so a stylesheet can't override them.
      mermaidConfig: {
        theme: 'base',
        themeVariables: {
          darkMode: true,
          fontFamily: "'Inter Variable', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
          background: '#191324', // surface
          primaryColor: '#201A2E', // surface-2
          primaryBorderColor: '#2B2340', // line
          primaryTextColor: '#EAE5F4', // text
          lineColor: '#9C92B8', // muted
          textColor: '#EAE5F4', // text
          actorBkg: '#201A2E', // surface-2
          actorBorder: '#2B2340', // line
          actorTextColor: '#EAE5F4', // text
          actorLineColor: '#6E6488', // faint
          signalColor: '#9C92B8', // muted
          signalTextColor: '#EAE5F4', // text
          noteBkgColor: '#201A2E', // surface-2
          noteBorderColor: '#221B33', // line-soft
          noteTextColor: '#9C92B8', // muted
          labelBoxBkgColor: '#201A2E', // surface-2
          labelBoxBorderColor: '#2B2340', // line
          labelTextColor: '#9C92B8', // muted
          loopTextColor: '#9C92B8', // muted
          activationBkgColor: '#201A2E', // surface-2
          activationBorderColor: '#2B2340', // line
          sequenceNumberColor: '#120E1A', // ink
        },
        sequence: {
          wrap: true,
        },
      },
    }),
  ],
  builderConfig: {
    plugins: [pluginSass()],
    output: {
      cleanDistPath: true,
      cssModules: isDevelopment
        ? undefined
        : {
            // Hash class names in production builds to match interface/ convention.
            localIdentName: '[hash:base64:6]',
          },
    },
    security: {
      sri: {
        enable: !isDevelopment,
        algorithm: 'sha512',
      },
    },
    resolve: {
      alias: {
        '@monetr/docs': path.resolve(__dirname, '.'),
      },
    },
    performance: {
      preload: {
        // Prevents dumb screen flash where the font is missing.
        type: 'all-assets',
        include: [/inter-latin-wght-normal.*\.woff2$/, /jetbrains-mono-latin-\d+-normal.*\.woff2$/],
      },
    },
    html: {
      tags: [
        {
          // Only include umami if we are doing a production build
          tag: 'script',
          attrs: !isDevelopment
            ? {
                defer: true,
                src: 'https://a.monetr.app/script.js',
                'data-website-id': 'ccbdfaf9-683f-4487-b97f-5516e1353715',
              }
            : {},
        },
      ],
    },
  },
  route: {
    cleanUrls: true,
  },
});