Skip to content

Commit

Permalink
first minor version release
Browse files Browse the repository at this point in the history
  • Loading branch information
trueberryless committed Nov 27, 2024
1 parent 4da03d6 commit ab7b842
Show file tree
Hide file tree
Showing 17 changed files with 2,303 additions and 45 deletions.
5 changes: 5 additions & 0 deletions .changeset/rich-parents-doubt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"starlight-plugin-show-latest-version-docs": minor
---

Documentation of first minor version of plugin
5 changes: 5 additions & 0 deletions .changeset/tiny-seas-rescue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"starlight-plugin-show-latest-version": minor
---

Release first minor version. Latest version in site title and virtual module export.
3 changes: 2 additions & 1 deletion docs/astro.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export default defineConfig({
plugins: [
starlightLinksValidator(),
starlightPluginShowLatestVersion({
repo: "HiDeoo/starlight-openapi",
repo: "trueberryless-org/starlight-plugin-show-latest-version",
}),
starlightPluginsDocsComponents({
pluginName: "starlight-plugin-show-latest-version",
Expand All @@ -35,6 +35,7 @@ export default defineConfig({
items: [
{ slug: "getting-started" },
{ slug: "configuration" },
{ slug: "exports" },
{ slug: "version-extraction-algorithm" },
],
},
Expand Down
23 changes: 21 additions & 2 deletions docs/src/content/docs/configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -66,24 +66,43 @@ Customize the badge used to display the latest version of your Starlight plugin.

The variant of the badge to use.

Here you can see how the different variants look like:
{ context.versionAvailable &&
(<>

<p>Here you can see how the different variants look like:</p>
<Badge text={context.version} size="medium" />
<Badge text={context.version} size="medium" variant="note" />
<Badge text={context.version} size="medium" variant="danger" />
<Badge text={context.version} size="medium" variant="success" />
<Badge text={context.version} size="medium" variant="caution" />
<Badge text={context.version} size="medium" variant="tip" />

</>)}

#### `size`

**Type:** `"small" | "medium" | "large"`
**Default:** `"medium"`

The size of the badge to use.

Here you can see how the different sizes look like:
{ context.versionAvailable &&
(<>

<p>Here you can see how the different sizes look like:</p>
<Badge text={context.version} size="small" />
<Badge text={context.version} size="medium" />
<Badge text={context.version} size="large" />

</>)
}

### `regexPattern`

**Type:** `string`

Override the regex pattern used to extract the version from the `tag_name` of the latest release on GitHub.

This is useful if your `tag_name` does not follow best practice and only necessary in rare cases. Nonetheless, it's supported by the Starlight Plugin Show Latest Version plugin.

Read more about how the version tag is being extracted from the GitHub release [here](/version-extraction-algorithm).
23 changes: 21 additions & 2 deletions docs/src/content/docs/demo.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,27 @@ description: Get a live demonstration of the Starlight Plugin Show Latest Versio
import { Badge } from "@astrojs/starlight/components";
import context from "virtual:starlight-plugin-show-latest-version-context";

See the blue version tag badge in the top right corner of this page as an example.
It should look like this:
{context.versionAvailable &&
(<>

<p>
See the blue version tag badge in the top right corner of this page as an
example. It should look like this:
</p>
<br />
<Badge text={context.version} size="medium" />

</>)}

{!context.versionAvailable &&
(<>

<p>
Uhh... something went wrong! <br /> No, not really.
</p>
<p>
You just currently are not able to see any demo because the version of the
plugin could not be determined. Try again later. :)
</p>

</>)}
56 changes: 56 additions & 0 deletions docs/src/content/docs/exports.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
title: Exports
description: An overview of all values and components exported by the Starlight Plugin Show Latest Version plugin.
---

import { Aside, Badge } from "@astrojs/starlight/components";
import context from "virtual:starlight-plugin-show-latest-version-context";

The Starlight Plugin Show Latest Version plugin exports a virtual module which allows you to use the plugin's calculated values in your own code.

## Import

```ts
import version from "virtual:starlight-plugin-show-latest-version-context";
```

## Usage

```mdx
{context.versionAvailable && <Badge text={context.version} size="medium" />}
```

{context.versionAvailable && (

<Aside type="tip" title="Preview">
<Badge text={context.version} size="medium" />
</Aside>

)}

## Available values

Since the type of the exported virtual modules looks like this:

```ts
export const VersionState = z.union([
z.object({
versionAvailable: z.literal(true),
version: z.string(),
versionWithoutPrefix: z.string(),
versionMajor: z.number(),
versionMinor: z.number(),
versionPatch: z.number(),
prerelease: z.string().optional(),
isPrereleaseVersion: z.boolean(),
prefix: z.string().optional(),
hasVPrefix: z.boolean(),
isStableVersion: z.boolean(),
}),
z.object({
versionAvailable: z.literal(false),
}),
]);
```

you have access to properties such as `version`, `versionWithoutPrefix`, `versionMajor`, `versionMinor`, `versionPatch`, `prerelease`, `isPrereleaseVersion`, `prefix`, `hasVPrefix`, `isStableVersion` under the condition that the version was parseable (`versionAvailable` is `true`).
55 changes: 45 additions & 10 deletions docs/src/content/docs/version-extraction-algorithm.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,54 @@ import { Badge } from "@astrojs/starlight/components";

The Starlight Plugin Show Latest Version plugin fetches the latest release of the repository on GitHub specified in the [`repo` configuration option](/configuration/#repo). It than extracts the `tag_name` which is the equivalent to the title of the release as you can see it on the [GitHub releases page](https://github.com/trueberryless-org/starlight-plugin-show-latest-version/releases).

The `tag_name` can be one of the following formats:
## Regex Pattern

- `X.Y.Z`
- `vX.Y.Z`
- `starlight-plugin-name@X.Y.Z`
- `starlight-plugin-name@vX.Y.Z`
The Starlight Plugin Show Latest Version plugin uses a regex pattern to extract the version (and prerelease) from the `tag_name` of the latest release on GitHub. The default pattern is:

This plugin will extract the `X.Y.Z` from the `tag_name`, prefix it with `v` and use it as the version tag. So in the end, all examples from above will look like this:
```ts wrap
/^(?:v|[^0-9\s]*@)?v?(?<version>[0-9]+\.[0-9]+\.[0-9]+)(?:-(?<prerelease>[0-9A-Za-z]+(?:\.[0-9A-Za-z]+)*))?(?![-.]|[^-\w.])$/;
```

<Badge text="vX.Y.Z" size="medium" />
You can override the pattern using the [`regexPattern` configuration option](/configuration/#regexpattern).

### Supported `tag_name`s

The `tag_name` can be one of the following formats which will produce these badges:

- `1.2.3` → <Badge text="v1.2.3" />
- `10.20.30` → <Badge text="v10.20.30" />
- `v1.2.3` → <Badge text="v1.2.3" />
- `release@1.2.3` → <Badge text="v1.2.3" />
- `name@v1.2.3` → <Badge text="v1.2.3" />
- `package-name@1.2.3` → <Badge text="v1.2.3" />
- `feature/branch@1.2.3` → <Badge text="v1.2.3" />
- `1.2.3-rc.1` → <Badge text="v1.2.3-rc.1" />
- `name@1.2.3-beta.2` → <Badge text="v1.2.3-beta.2" />
- `v1.2.3-alpha.34` → <Badge text="v1.2.3-alpha.34" />
- `package-name@1.2.3-rc.1` → <Badge text="v1.2.3-rc.1" />
- `1.2.3-alpha` → <Badge text="v1.2.3-alpha" />
- `1.2.3-beta` → <Badge text="v1.2.3-beta" />
- `1.2.3-rc` → <Badge text="v1.2.3-rc" />
- `1.2.3-feature.test` → <Badge text="v1.2.3-feature.test" />
- `1.2.3-long.complex.prerelease.tag` → <Badge text="v1.2.3-long.complex.prerelease.tag" />

### Invalid `tag_name`s

Here are examples of `tag_name` formats which would not be supported by the default version extraction algorithm:

- `X.Y` -- no semantic versioning because it is missing the third number
- `W.X.Y.Z` -- no semantic versioning because it has too many numbers
- `X.Y.Z-rc.1`
- `1.2` → no semantic versioning because it is missing the third number
- `v1.2` → no semantic versioning because it is missing the third number
- `1.2.` → invalid version format, incomplete
- `v1.2.` → invalid version format, incomplete
- `1.2.3.4` → too many version segments
- `1.2.3.` → invalid version format, trailing dot
- `v1.2.3.4` → too many version segments
- `1.2.3-` → invalid prerelease format
- `1.2.3-.rc` → invalid prerelease format
- `1.2.3-rc.` → invalid prerelease format
- `1.2.3--rc` → invalid prerelease format
- `random-text` → non-version string
- `` → empty string
- `123` → non-version string
- `v1.2.3-special!char` → invalid version format with special characters
- `1.2.3-pre release` → invalid version format due to space
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const SEMVER_PATTERN =
/^(?:v|[^0-9\s]*@)?v?(?<version>[0-9]+\.[0-9]+\.[0-9]+)(?:-(?<prerelease>[0-9A-Za-z]+(?:\.[0-9A-Za-z]+)*))?(?![-.]|[^-\w.])$/;
7 changes: 7 additions & 0 deletions packages/starlight-plugin-show-latest-version/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/** @type {import('ts-jest').JestConfigWithTsJest} **/
export default {
testEnvironment: "node",
transform: {
"^.+.tsx?$": ["ts-jest",{}],
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const configSchema = z.object({
size: z.enum(["small", "medium", "large"]).default("medium"),
})
.default({}),
regexPattern: z.string().optional(),
});

export function validateConfig(
Expand Down
28 changes: 20 additions & 8 deletions packages/starlight-plugin-show-latest-version/libs/types.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
import { z } from "astro/zod";

const contextSchema = z.object({
version: z.string(),
versionWithoutPrefix: z.string(),
versionPatch: z.number(),
versionMinor: z.number(),
versionMajor: z.number(),
});
// Enum-like structure for the version state
export const VersionState = z.union([
z.object({
versionAvailable: z.literal(true),
version: z.string(),
versionWithoutPrefix: z.string(),
versionMajor: z.number(),
versionMinor: z.number(),
versionPatch: z.number(),
prerelease: z.string().optional(),
isPrereleaseVersion: z.boolean(),
prefix: z.string().optional(),
hasVPrefix: z.boolean(),
isStableVersion: z.boolean(),
}),
z.object({
versionAvailable: z.literal(false),
}),
]);

export type StarlightPluginShowLatestVersionContext = z.infer<
typeof contextSchema
typeof VersionState
>;
40 changes: 26 additions & 14 deletions packages/starlight-plugin-show-latest-version/libs/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { SEMVER_PATTERN } from "../consts/semantic.version.pattern";
import type { StarlightPluginShowLatestVersionConfig } from "./config";
import type { StarlightPluginShowLatestVersionContext } from "./types";

Expand All @@ -14,35 +15,46 @@ export default async function fetchVersion(
return response.json();
});

// Extract and normalize the version
const tagName = data.tag_name || "";
const match = tagName.match(/(?:.*@)?(?<version>[0-9]+\.[0-9]+\.[0-9]+)/);
if (!tagName) {
return { versionAvailable: false }; // No release available
}

const match = tagName.match(config.regexPattern ?? SEMVER_PATTERN);

if (!match) {
throw new Error(`Failed to parse version from: ${tagName}`);
return { versionAvailable: false }; // No valid version found
}

const versionWithoutPrefix = match.groups?.version || "";
const version = `v${versionWithoutPrefix}`;
const versionPatch = Number(versionWithoutPrefix.split(".")[2] || 0);
const versionMinor = Number(versionWithoutPrefix.split(".")[1] || 0);
const versionMajor = Number(versionWithoutPrefix.split(".")[0] || 0);
const [versionMajor = 0, versionMinor = 0, versionPatch = 0] =
versionWithoutPrefix.split(".").map(Number);

const prerelease = match.groups?.prerelease;
const isPrereleaseVersion = !!prerelease;
const version = isPrereleaseVersion
? `${versionWithoutPrefix}-${prerelease}`
: `v${versionWithoutPrefix}`;

const prefixMatch = tagName.match(/^(.*?)v?[0-9]/);
const prefix = prefixMatch ? prefixMatch[1] : undefined;
const hasVPrefix = tagName.startsWith("v") || tagName.includes("@v");

return {
versionAvailable: true,
version,
versionWithoutPrefix,
versionPatch,
versionMinor,
versionMajor,
prerelease,
isPrereleaseVersion,
prefix,
hasVPrefix,
isStableVersion: !isPrereleaseVersion,
};
} catch (error) {
console.error(error);
return {
version: "v0.0.0",
versionWithoutPrefix: "0.0.0",
versionPatch: 0,
versionMinor: 0,
versionMajor: 0,
}; // Fallback version
return { versionAvailable: false }; // Fallback: no version available
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import type { Props } from '../props';
import { Badge } from '@astrojs/starlight/components';
const { siteTitle, siteTitleHref } = Astro.props;
const version = context.version;
---

<a href={siteTitleHref} class="site-title sl-flex">
Expand Down Expand Up @@ -38,10 +36,10 @@ const version = context.version;
<span class:list={{ 'sr-only': config.logo?.replacesTitle }}>
{siteTitle}
</span>
{version && (
{context.versionAvailable && (
<starlight-plugin-show-latest-version>
<a href="https://github.com/trueberryless-org/starlight-cooler-credit/releases/latest" class="starlight-plugin-show-latest-version-link">
<Badge text={version} variant={pluginConfig.badge.variant} size={pluginConfig.badge.size} class='starlight-plugin-show-latest-version-badge'/>
<Badge text={context.version} variant={pluginConfig.badge.variant} size={pluginConfig.badge.size} class='starlight-plugin-show-latest-version-badge'/>
</a>
</starlight-plugin-show-latest-version>
)}
Expand Down
9 changes: 8 additions & 1 deletion packages/starlight-plugin-show-latest-version/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@
},
"devDependencies": {
"@astrojs/starlight": "^0.29.0",
"astro": "^4.16.10"
"@jest/globals": "^29.7.0",
"@types/jest": "^29.5.14",
"astro": "^4.16.10",
"jest": "^29.7.0",
"ts-jest": "^29.2.5"
},
"peerDependencies": {
"@astrojs/starlight": ">=0.29"
Expand All @@ -35,5 +39,8 @@
},
"publishConfig": {
"access": "public"
},
"scripts": {
"test": "jest"
}
}
Loading

0 comments on commit ab7b842

Please sign in to comment.