From c3cb5502e8409fc93161929fe380afd3853fb4de Mon Sep 17 00:00:00 2001 From: Pat Garrity Date: Sun, 24 Mar 2024 04:02:38 +0000 Subject: [PATCH] (patch) Pre-commit and builds --- .forgejo/workflows/pull_request.yaml | 2 +- .forgejo/workflows/release.yaml | 2 +- README.md | 20 +++++++++++++ src/main/scala/gs/slug/v0/Slug.scala | 34 +++++++++++------------ src/test/scala/gs/slug/v0/SlugTests.scala | 1 + 5 files changed, 40 insertions(+), 19 deletions(-) diff --git a/.forgejo/workflows/pull_request.yaml b/.forgejo/workflows/pull_request.yaml index 700fa3d..8ca9d2b 100644 --- a/.forgejo/workflows/pull_request.yaml +++ b/.forgejo/workflows/pull_request.yaml @@ -26,7 +26,7 @@ jobs: pre-commit run --all-files - name: 'Prepare Versioned Build' run: | - latest_git_tag="$(git describe --tags --abbrev=0)" + latest_git_tag="$(git describe --tags --abbrev=0 || echo 'No Tags')" latest_commit_message="$(git show -s --format=%s HEAD)" if [[ "$latest_commit_message" == *"(major)"* ]]; then export GS_RELEASE_TYPE="major" diff --git a/.forgejo/workflows/release.yaml b/.forgejo/workflows/release.yaml index 9c76938..ecbd203 100644 --- a/.forgejo/workflows/release.yaml +++ b/.forgejo/workflows/release.yaml @@ -27,7 +27,7 @@ jobs: pre-commit run --all-files - name: 'Prepare Versioned Build' run: | - latest_git_tag="$(git describe --tags --abbrev=0)" + latest_git_tag="$(git describe --tags --abbrev=0 || echo 'No Tags')" latest_commit_message="$(git show -s --format=%s HEAD)" if [[ "$latest_commit_message" == *"(major)"* ]]; then export GS_RELEASE_TYPE="major" diff --git a/README.md b/README.md index 9cf89b9..9dfa7b8 100644 --- a/README.md +++ b/README.md @@ -17,3 +17,23 @@ externalResolvers += val GsSlug: ModuleID = "gs" %% "gs-slug-v0" % "0.1.0" ``` + +## Slug Type + +`Slug` is the type exposed by this library. It is an extremely small, +restricted, opaque type (`String`) that adheres to the following regular +expression: + +``` +^[a-z0-9]+(?:\-[a-z0-9]+)*$ +``` + +This type is intended for use in the following scenarios: + +- Restricted ASCII is acceptable. +- URL safety is desired. + +Additionally, `Slug` is usually intended to be unique within some _context_, +where the implementation defines the context. For example, if some organization +owns a number of repositories, each repository might have a `Slug` which is +unique within that organization. diff --git a/src/main/scala/gs/slug/v0/Slug.scala b/src/main/scala/gs/slug/v0/Slug.scala index 2e634a2..0d1d882 100644 --- a/src/main/scala/gs/slug/v0/Slug.scala +++ b/src/main/scala/gs/slug/v0/Slug.scala @@ -2,16 +2,15 @@ package gs.slug.v0 import scala.util.matching.Regex -/** - * Restricted string intended to be used as a unique, URL-safe identifier +/** Restricted string intended to be used as a unique, URL-safe identifier * within some specific context (not a globally unique identifier). This type * adheres to the regular expression: `^[a-z0-9]+(?:\-[a-z0-9]+)*$` * * Essentially, Slugs follow these rules: * - * - Segments are defined as lowercase alphanumeric ASCII strings. - * - Segments are separated by exactly one `-` character. - * - At least one segment is required. + * - Segments are defined as lowercase alphanumeric ASCII strings. + * - Segments are separated by exactly one `-` character. + * - At least one segment is required. * * If you need full unicode support, more characters, fewer constraints, etc. * don't use this type. @@ -22,21 +21,22 @@ object Slug: val SlugPattern: Regex = "^[a-z0-9]+(?:\\-[a-z0-9]+)*$".r - /** - * Instantiate a [[Slug]] by validating the candidate input. - * - * @param candidate The candidate string used to create the [[Slug]]. - * @return The [[Slug]], or `None` if the candidate is invalid. - */ - def validate(candidate: String): Option[Slug] = + /** Instantiate a [[Slug]] by validating the candidate input. + * + * @param candidate + * The candidate string used to create the [[Slug]]. + * @return + * The [[Slug]], or `None` if the candidate is invalid. + */ + def validate(candidate: String): Option[Slug] = if SlugPattern.matches(candidate) then Some(candidate) else None given CanEqual[Slug, Slug] = CanEqual.derived extension (slug: Slug) - /** - * Render this [[Slug]] as a string. - * - * @return The string representation of this [[Slug]]. - */ + /** Render this [[Slug]] as a string. + * + * @return + * The string representation of this [[Slug]]. + */ def str(): String = slug diff --git a/src/test/scala/gs/slug/v0/SlugTests.scala b/src/test/scala/gs/slug/v0/SlugTests.scala index 5fbf7e5..e15a238 100644 --- a/src/test/scala/gs/slug/v0/SlugTests.scala +++ b/src/test/scala/gs/slug/v0/SlugTests.scala @@ -1,6 +1,7 @@ package gs.slug.v0 class SlugTests extends munit.FunSuite: + test("should instantiate valid slugs") { ('a' to 'z').foreach(c => assertValidSlug(c.toString())) ('0' to '9').foreach(c => assertValidSlug(c.toString()))