diff --git a/src/site.ts b/src/site.ts index 231903c..7f43513 100644 --- a/src/site.ts +++ b/src/site.ts @@ -21,43 +21,125 @@ export const updateLatest = async (versionsDir: string, latestVersion: string): await cp(join(versionsDir, latestVersion), latestDir, { recursive: true }); }; -const renderIndexPage = (versions: string[], latest?: string): string => { - const latestLink = latest - ? `
  • latest (${latest})
  • \n ` - : ''; - const versionLinks = versions - .map((version) => `
  • ${version}
  • `) - .join('\n '); - return ` +const renderStylesheets = (styleBase?: string): string => { + if (styleBase === undefined) { + return ''; + } + return ` + + + + + `; +}; + +const renderLatestCard = (latest?: string): string => { + if (latest === undefined) { + return `
    +
    + No stable release yet + +
    +
    `; + } + return `
    +
    + Latest stable release +

    v${latest}

    + +
    +
    `; +}; + +const renderPrereleaseBadge = (version: string): string => { + if (semver.prerelease(version) === null) { + return ''; + } + return 'pre-release'; +}; + +const renderVersionItem = (version: string): string => + `
  • ${version}${renderPrereleaseBadge(version)}
  • `; + +const findStyleBase = (versions: string[], latest?: string): string | undefined => { + if (latest !== undefined) { + return `styles/${LATEST_DIR}`; + } + if (versions.length > 0) { + return `styles/${versions[0]}`; + } + return undefined; +}; + +const renderVersionList = (versions: string[]): string => { + if (versions.length === 0) { + return '

    No versions have been published yet.

    '; + } + return `
      \n ${versions.map(renderVersionItem).join('\n ')}\n
    `; +}; + +export const renderIndexPage = (versions: string[], latest?: string): string => + ` Ippon UI Pattern Library - + + ${renderStylesheets(findStyleBase(versions, latest))} -

    Ippon UI Pattern Library

    -

    Published versions of @ippon-ui/styles:

    - -

    Versions are also listed in versions.json.

    +
    +
    +
    +
    + Ippon Technologies +
    +
    +
    +
    +
    +
    +
    +

    Ippon UI

    +

    The design system behind Ippon products.

    +
    +
    +
    +

    Styles

    +

    + The Pattern Library — every published version of + @ippon-ui/styles, mirrored from npm. +

    +
    + ${renderLatestCard(latest)} +
    +

    All versions

    + ${renderVersionList(versions)} +
    +
    +
    + +
    +
    +
    +
    `; -}; export const generateSitePages = async ( siteDir: string, diff --git a/test/site.test.ts b/test/site.test.ts index ce86b43..7d1730f 100644 --- a/test/site.test.ts +++ b/test/site.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from 'vitest'; -import { findLatestStable } from '../src/site.ts'; +import { findLatestStable, renderIndexPage } from '../src/site.ts'; describe('findLatestStable', () => { it('should return the highest version', () => { @@ -15,3 +15,55 @@ describe('findLatestStable', () => { expect(findLatestStable([])).toBeUndefined(); }); }); + +describe('renderIndexPage', () => { + it('should link every version', () => { + const html = renderIndexPage(['0.0.2', '0.0.1'], '0.0.2'); + expect(html).toContain('href="styles/0.0.2/index.html"'); + expect(html).toContain('href="styles/0.0.1/index.html"'); + expect(html).toContain('href="versions.json"'); + }); + + it('should feature the latest stable version', () => { + const html = renderIndexPage(['0.0.2'], '0.0.2'); + expect(html).toContain('href="styles/latest/index.html"'); + expect(html).toContain('v0.0.2'); + }); + + it('should style the page with the pattern library of the latest stable version', () => { + const html = renderIndexPage(['0.0.2'], '0.0.2'); + expect(html).toContain('href="styles/latest/tikui.css"'); + }); + + it('should not link latest when there is no stable version', () => { + const html = renderIndexPage(['0.1.0-beta.1']); + expect(html).not.toContain('href="styles/latest/index.html"'); + expect(html).toContain('No stable release yet'); + }); + + it('should fall back to the highest version stylesheet when there is no stable version', () => { + const html = renderIndexPage(['0.1.0-beta.1']); + expect(html).toContain('href="styles/0.1.0-beta.1/tikui.css"'); + }); + + it('should render without a stylesheet when no version is published', () => { + const html = renderIndexPage([]); + expect(html).not.toContain('tikui.css'); + }); + + it('should tag prereleases', () => { + const html = renderIndexPage(['0.1.0-beta.1', '0.0.1'], '0.0.1'); + expect(html.match(/pre-release/g)).toHaveLength(1); + }); + + it('should render an empty state when no version is published', () => { + const html = renderIndexPage([]); + expect(html).toContain('No versions have been published yet.'); + }); + + it('should only use pattern library styles', () => { + const html = renderIndexPage(['0.0.2'], '0.0.2'); + expect(html).not.toContain('