Ctrl K
ComunidadGuías…

web/vite.changelog.ts

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

Archivo original ↗Preguntar a KiBot
// The What's new notes as a Vite plugin (vite.config.ts): CHANGELOG.md, read at build time.
import { existsSync, readFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import type { Plugin } from 'vite';
import { RELEASE_VERSION, releaseSection, releaseVersions, unreleasedSection } from './src/whatsnew/changelog.ts';

/**
 * The What's new dialog's notes: the repository's CHANGELOG.md, read at build time (docker/web.Dockerfile copies it
 * next to web/). `virtual:mdmesh-changelog` holds the versions with a section, and loads the sections themselves as
 * a chunk of their own (`virtual:mdmesh-changelog/notes`), cut by release/changelog-section.sh's rules
 * (src/whatsnew/changelog.ts). Unreleased is in dev builds only (`vite`, and tests). Types: src/whatsnew/virtual.d.ts.
 * A production build fails without CHANGELOG.md; a dev server or test run only warns. `file` is for tests.
 */
export function changelogNotes(
  appVersion: string | undefined,
  file = fileURLToPath(new URL('../CHANGELOG.md', import.meta.url)),
): Plugin {
  const INDEX = 'virtual:mdmesh-changelog';
  const NOTES = 'virtual:mdmesh-changelog/notes';
  let dev = true;
  return {
    name: 'mdmesh-changelog',
    configResolved(config) {
      dev = !config.isProduction;
    },
    resolveId(id) {
      return id === INDEX || id === NOTES ? `\0${id}` : null;
    },
    load(id) {
      if (id !== `\0${INDEX}` && id !== `\0${NOTES}`) return null;
      let text = '';
      if (existsSync(file)) {
        this.addWatchFile(file);
        text = readFileSync(file, 'utf8');
      } else if (!dev) {
        // A release image without its notes would show What's new to no one, silently: refuse to build it.
        this.error(`${file} not found: a production build needs it for What's new (docker/web.Dockerfile copies it next to web/)`);
      } else {
        this.warn(`${file} not found: the console runs without What's new notes`);
      }
      const versions = releaseVersions(text);
      const unreleased = dev ? unreleasedSection(text) : null;
      if (id === `\0${INDEX}`) {
        const v = appVersion?.replace(/^v/, '');
        if (!dev && v && RELEASE_VERSION.test(v) && !versions.includes(v)) {
          this.warn(`CHANGELOG.md has no section for VITE_APP_VERSION ${v}: What's new shows nothing for it`);
        }
        return [
          `export const versions = ${JSON.stringify(versions)};`,
          `export const hasUnreleased = ${unreleased !== null};`,
          `export const load = () => import(${JSON.stringify(NOTES)});`,
        ].join('\n');
      }
      const sections = Object.fromEntries(versions.map((v) => [v, releaseSection(text, v)]));
      return `export const sections = ${JSON.stringify(sections)};\nexport const unreleased = ${JSON.stringify(unreleased)};`;
    },
  };
}