{"id":13413472,"url":"https://github.com/chanced/caps","last_synced_at":"2025-04-28T16:24:44.148Z","repository":{"id":58309190,"uuid":"530000825","full_name":"chanced/caps","owner":"chanced","description":"A Unicode-based case conversion library for Go","archived":false,"fork":false,"pushed_at":"2023-12-30T16:57:05.000Z","size":207,"stargazers_count":58,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-30T11:12:02.609Z","etag":null,"topics":["case-conversion","case-converter","case-folding","casefold","go","golang","unicode","unicode-case-folding"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/chanced.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2022-08-28T23:04:45.000Z","updated_at":"2025-01-07T15:04:33.000Z","dependencies_parsed_at":"2023-12-30T17:53:15.991Z","dependency_job_id":"a40483e8-746c-437b-8f6b-6af643b01119","html_url":"https://github.com/chanced/caps","commit_stats":{"total_commits":173,"total_committers":1,"mean_commits":173.0,"dds":0.0,"last_synced_commit":"488e6b8e2693284f1d0882afa863725c1a307dd1"},"previous_names":[],"tags_count":52,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chanced%2Fcaps","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chanced%2Fcaps/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chanced%2Fcaps/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/chanced%2Fcaps/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/chanced","download_url":"https://codeload.github.com/chanced/caps/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251343791,"owners_count":21574426,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["case-conversion","case-converter","case-folding","casefold","go","golang","unicode","unicode-case-folding"],"created_at":"2024-07-30T20:01:41.160Z","updated_at":"2025-04-28T16:24:44.124Z","avatar_url":"https://github.com/chanced.png","language":"Go","readme":"# caps is a case conversion library for go\n\n[![Go Reference](https://pkg.go.dev/badge/github.com/chanced/caps.svg)](https://pkg.go.dev/github.com/chanced/caps)\n[![Latest Version](https://img.shields.io/github/v/tag/chanced/caps.svg?sort=semver\u0026style=flat-square\u0026label=version\u0026color=blue)](https://img.shields.io/github/v/tag/chanced/caps.svg?sort=semver\u0026style=flat-square\u0026label=version\u0026color=blue)\n![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/chanced/caps.svg?style=flat-square\u0026label=go)\n[![GoReportCard](https://goreportcard.com/badge/github.com/chanced/caps?style=flat-square)](https://goreportcard.com/report/github.com/chanced/caps)\n[![Codecov](https://img.shields.io/codecov/c/github/chanced/caps?style=flat-square\u0026token=6601V8MSG3)](https://codecov.io/gh/chanced/caps)\n![Build Status](https://img.shields.io/github/actions/workflow/status/chanced/caps/main.yaml?style=flat-square)\n\ncaps is a unicode aware, case conversion library for Go.\n\n\u003c!-- -   [Supported Case Conversions](#supported-case-conversions)\n-   [Install](#install)\n-   [Example](#example)\n-   [Word boundaries](#word-boundaries)\n-   [Replacements](#replacements)\n    -   [Default replacements](#default-replacements)\n-   [Customizing the `Converter`](#customizing-the-converter)\n    -   [Using caps.Caps](#using-capscaps)\n    -   [Creating isolated `caps.StdConverter` instances](#creating-isolated-capsstdconverter-instances)\n    -   [Modifying the `caps.DefaultConverter` global](#modifying-the-capsdefaultconverter-global)\n    -   [Creating a custom `caps.Converter`](#creating-a-custom-capsconverter)\n-   [Support for special case unicode (e.g. Turkish, Azeri)](#support-for-special-case-unicode-eg-turkish-azeri)\n-   [text.Text](#texttext)\n-   [Benchmarks](#benchmarks)\n-   [License](#license) --\u003e\n\n## Supported Case Conversions\n\nThe following case conversions are available:\n\n-   Camel Case (e.g. CamelCase)\n-   Lower Camel Case (e.g. lowerCamelCase)\n-   Snake Case (e.g. snake_case)\n-   Screaming Snake Case (e.g. SCREAMING_SNAKE_CASE)\n-   Kebab Case (e.g. kebab-case)\n-   Screaming Kebab Case(e.g. SCREAMING-KEBAB-CASE)\n-   Dot Notation Case (e.g. dot.notation.case)\n-   Screaming Dot Notation Case (e.g. DOT.NOTATION.CASE)\n-   Title Case (e.g. Title Case)\n-   Other deliminations\n\n## Install\n\n```\ngo get github.com/chanced/caps\n```\n\n## Example\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/chanced/caps\"\n)\nfunc main() {\n\tfmt.Println(caps.ToCamel(\"http request\"))\n\t// Output:\n\t// HTTPRequest\n\tfmt.Println(caps.ToLowerCamel(\"some_id\"))\n\t// Output:\n\t// someID\n\tfmt.Println(caps.ToLowerCamel(\"SomeID\", caps.WithReplaceStyleCamel()))\n\t// Output:\n\t// someId\n\n\t// Alternatively:\n\tcapsJS := caps.New(caps.Config{\n\t\tAllowedSymbols: \"$\",\n\t\tReplaceStyle:   caps.ReplaceStyleCamel,\n\t})\n\tfmt.Println(capsJS.ToCamel(\"SomeID\"))\n\t// Output:\n\t// someId\n}\n\n```\n\n[go playground link](https://go.dev/play/p/bJvbMAmtZzV)\n\n## Word boundaries\n\nWord boundaries are determined by the `caps.Converter`. The provided implementation, `caps.StdConverter`,\ndelegates the boundary detection to `caps.Tokenizer`. The provided implementation, `caps.StdTokenizer`,\nuses the following rules:\n\n-   The following characters are considered word breaks `\" _.!?:;$-(){}[]#@\u0026+~\"` unless present in `AllowedSymbols`\n-   Strings with all upper case characters are split by the above symbols or by\n    numbers, unless the character is allowed in a number based on the following rules:\n    -   'v' or 'V' followed by numbers\n    -   '.' before/after a number and only once\n    -   'e' or 'E' if in the fractional part of a number and only once\n    -   '-', '+' if at the start and followed by either a number or '.' and a\n        number or in the fractional part proceeded by 'e' or 'E'\n    -   additional rules can be added through the number rules (e.g. `WithNumberRules`)\n    -   NOTE: If '.', '+', '-' are not in the `AllowedSymbols` they are\n        considered breaks even for numbers\n-   When a string consists of both upper case and lower case letters, upper case\n    letters are considered boundaries (e.g. `\"ThisVar\"` would be tokenized into `[\"This\", \"Var\"]`)\n-   When mixed with lower and upper case characters, sequences of upper case are\n    broken up into token strings (e.g. `\"SomeID\"` would be tokenized into `[\"Some\", \"I\", \"D\"]`).\n-   Replacement rules are then evaluated based on the token strings, which may\n    combine them based on the rules below.\n\n## Replacements\n\n`caps.StdConverter` also allows users to register `caps.Replacement`s for\ninitialism replacements. Each `Replacement` is indexed in a trie (see\n[Index](https://github.com/chanced/caps/blob/main/index/index.go)).\n\n-   Multi-rune token strings are searched independently unless followed by a number (e.g.\n    `\"ID\"`, `\"UTF8\"`).\n-   Sequences of single rune token (e.g.`[\"U\", \"U\", \"I\", \"D\"]`) are\n    evaluated as a potential `Replacement` until a non-match is\n    found or the sequence is broken by a token string with more than one rune.\n\n### Default replacements\n\n```go\n{\"Acl\", \"ACL\"}\n{\"Api\", \"API\"}\n{\"Ascii\", \"ASCII\"}\n{\"Cpu\", \"CPU\"}\n{\"Css\", \"CSS\"}\n{\"Dns\", \"DNS\"}\n{\"Eof\", \"EOF\"}\n{\"Guid\", \"GUID\"}\n{\"Html\", \"HTML\"}\n{\"Http\", \"HTTP\"}\n{\"Https\", \"HTTPS\"}\n{\"Id\", \"ID\"}\n{\"Ip\", \"IP\"}\n{\"Json\", \"JSON\"}\n{\"Lhs\", \"LHS\"}\n{\"Qps\", \"QPS\"}\n{\"Ram\", \"RAM\"}\n{\"Rhs\", \"RHS\"}\n{\"Rpc\", \"RPC\"}\n{\"Sla\", \"SLA\"}\n{\"Smtp\", \"SMTP\"}\n{\"Sql\", \"SQL\"}\n{\"Ssh\", \"SSH\"}\n{\"Tcp\", \"TCP\"}\n{\"Tls\", \"TLS\"}\n{\"Ttl\", \"TTL\"}\n{\"Udp\", \"UDP\"}\n{\"Ui\", \"UI\"}\n{\"Uid\", \"UID\"}\n{\"Uuid\", \"UUID\"}\n{\"Uri\", \"URI\"}\n{\"Url\", \"URL\"}\n{\"Utf8\", \"UTF8\"}\n{\"Vm\", \"VM\"}\n{\"Xml\", \"XML\"}\n{\"Xmpp\", \"XMPP\"}\n{\"Xsrf\", \"XSRF\"}\n{\"Xss\", \"XSS\"}\n```\n\nIf you would like to add or remove entries from that list, you have a few\noptions. See below.\n\n## Customizing the `Converter`\n\n### Using caps.Caps\n\nThis is likely your best option. You can create and utilize an instance of\n`caps.Caps` which has all of the conversions as methods:\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/chanced/caps\"\n)\n\nfunc main() {\n\tc := caps.New(caps.Config{\n\t\tReplacements: []caps.Replacement{\n\t\t\t{Camel: \"Ex\", Screaming: \"EX\"},\n\t\t\t// ... your replacements\n\t\t},\n\t})\n\tfmt.Println(c.ToCamel(\"some ex\"))\n\t// Output:\n\t// SomeEX\n}\n```\n\n[go playground link](https://go.dev/play/p/8G6Yl-9I030)\n\n### Creating isolated `caps.StdConverter` instances\n\nYou can pass a new instance of `caps.StdConverter` with a new set of\n`caps.Replacement`.\n\n```go\n    package main\n    import (\n        \"fmt\"\n        \"github.com/chanced/caps\"\n        \"github.com/chanced/caps/token\"\n    )\n    func main() {\n        replacements := []caps.Replacement{\n            {\"Ex\", \"EX\" },\n            // ... your replacements\n        }\n        converter := caps.NewConverter(replacements, caps.DefaultTokenizer, token.DefaultCaser)\n        fmt.Println(caps.ToCamel(\"ex id\", caps.WithConverter(converter)))\n        // note: ID was not in the replacement list above\n        // Output:\n        // \"EXId\"\n       fmt.Println(caps.ToCamel(\"ex id\"))\n        // Output:\n        // ExID\n    }\n```\n\n[go playground link](https://go.dev/play/p/jlFAj3ujhTW)\n\n### Modifying the `caps.DefaultConverter` global\n\nYou can update `caps.DefaultConverter`. You should set it before you make any\nconversions. Otherwise, you'll need guard your usage of the library accordingly\n(e.g. a mutex).\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/chanced/caps\"\n)\n\nfunc main() {\n\tconverter, _ := caps.DefaultConverter.(caps.StdConverter)\n\tconverter.Set(\"Gcp\", \"GCP\")\n\tfmt.Println(caps.ToCamel(\"some_gcp_var\"))\n\t// Output:\n\t// SomeGCPVar\n}\n\n```\n\n[go playground link](https://go.dev/play/p/GcEHFAR8zHK)\n\n### Creating a custom `caps.Converter`\n\nFinally, if you are so inclined, you can create your own `caps.Converter`. This\ncould be as simple as implementing the single `Convert` method, calling\n`caps.DefaultConverter.Convert`, and then modifying the result.\n\n```go\npackage main\nimport (\n    \"fmt\"\n    \"github.com/chanced/caps\"\n)\ntype MyConverter struct{}\nfunc (MyConverter) Convert(req caps.ConvertRequest) string {\n    res := caps.DefaultConverter.Convert(req)\n    if req.Style.IsLowerCamel() \u0026\u0026 req.ReplaceStyle.IsCamel() \u0026\u0026 res == \"id\" {\n        return \"_id\"\n    }\n    return res\n}\nfunc main() {\n    fmt.Println(caps.ToLowerCamel(\"ID\", caps.WithReplaceStyleCamel(), caps.WithConverter(MyConverter{})))\n    // Output:\n    // _id\n}\n```\n\n[go playground link](https://go.dev/play/p/kmtwZlP41S9)\n\n## Support for special case unicode (e.g. Turkish, Azeri)\n\ncaps supports Turkish and Azeri through the `token.Caser` interface. It is\nsatisfied by `unicode.TurkishCase` and `unicode.AzeriCase`. `token.TurkishCaser`\nand `token.AzeriCaser` are available as pointers to those variables (although\nyou can use the unicode variables directly).\n\nFor example, to use Turkish, you would need to instantiate a few variables:\n\n```go\npackage main\nimport (\n    \"github.com/chanced/caps\"\n    \"github.com/chanced/caps/token\"\n\n)\nfunc main() {\n    tokenizer := caps.NewTokenizer(caps.DEFAULT_DELIMITERS, token.TurkishCaser)\n    // I suppose these would need to be specific to Turkish?\n    // if not, you can just use caps.DefaultReplacements\n    replacements := []caps.Replacement{\n        { Camel: \"Http\", Screaming: \"HTTP\" }, // just an example\n    }\n    turkish := caps.NewConverter(replacements, tokenizer, token.TurkishCaser)\n\n    // to use this as your default throughout your application\n    // you can overwrite caps.DefaultConverter\n    //\n    // caps.DefaultConverter = turkish\n    //\n    // otherwise, you can pass in the converter to the config for each call:\n    fmt.Println(caps.ToScreamingKebab(\"i ı\", caps.WithConverter(turkish)))\n    // Output:\n    // İ-I\n}\n```\n\n[go playground link](https://go.dev/play/p/aKfuU5eZJgp)\n\n## text pkg\n\nThe `text` package contains two types:\n\n-   `Text` which has all of the case conversions and relevant functions from strings as methods.\n-   `Texts` which is a sortable slice of Text with a few helper methods\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"github.com/chanced/caps/text\"\n)\n\nfunc main() {\n\tt := text.Text(\"Hello World\")\n\tfor _, p := range t.ToKebab().Split(\"-\") {\n\t\tfmt.Println(p)\n\t}\n\t// Output:\n\t// hello\n\t// world\n}\n```\n\n[go playground link](https://go.dev/play/p/MOYKz4ySpAv)\n\n## Benchmarks\n\n```\ninput: \"Example Uuid.\"\n```\n\n```\ngoos: darwin\ngoarch: arm64\npkg: github.com/chanced/caps\n```\n\nUsing a `caps.Caps` instance:\n\n```\nBenchmarkCapsToTitle\nBenchmarkCapsToTitle-10                   \t 2488982\t       470.2 ns/op\t     200 B/op\t       8 allocs/op\nBenchmarkCapsToCamel\nBenchmarkCapsToCamel-10                   \t 2474846\t       467.8 ns/op\t     200 B/op\t       8 allocs/op\nBenchmarkCapsToLowerCamel\nBenchmarkCapsToLowerCamel-10              \t 2650843\t       451.0 ns/op\t     200 B/op\t       8 allocs/op\nBenchmarkCapsToSnake\nBenchmarkCapsToSnake-10                   \t 2619945\t       456.9 ns/op\t     200 B/op\t       8 allocs/op\nBenchmarkCapsToScreamingSnake\nBenchmarkCapsToScreamingSnake-10          \t 2591302\t       461.9 ns/op\t     200 B/op\t       8 allocs/op\nBenchmarkCapsToKebab\nBenchmarkCapsToKebab-10                   \t 2621020\t       457.0 ns/op\t     200 B/op\t       8 allocs/op\nBenchmarkCapsToScreamingKebab\nBenchmarkCapsToScreamingKebab-10          \t 2593428\t       466.3 ns/op\t     200 B/op\t       8 allocs/op\nBenchmarkCapsToDotNotation\nBenchmarkCapsToDotNotation-10             \t 2575178\t       463.0 ns/op\t     200 B/op\t       8 allocs/op\nBenchmarkCapsToScreamingDotNotation\nBenchmarkCapsToScreamingDotNotation-10    \t 2526782\t       472.8 ns/op\t     200 B/op\t       8 allocs/op\n```\n\nUsing top-level functions:\n\n```\nBenchmarkToTitle\nBenchmarkToTitle-10                       \t 2316468\t       519.1 ns/op\t     200 B/op\t       8 allocs/op\nBenchmarkToCamel\nBenchmarkToCamel-10                       \t 2327542\t       516.8 ns/op\t     200 B/op\t       8 allocs/op\nBenchmarkToLowerCamel\nBenchmarkToLowerCamel-10                  \t 2372518\t       505.3 ns/op\t     200 B/op\t       8 allocs/op\nBenchmarkToSnake\nBenchmarkToSnake-10                       \t 2337992\t       511.8 ns/op\t     200 B/op\t       8 allocs/op\nBenchmarkToScreamingSnake\nBenchmarkToScreamingSnake-10              \t 2313232\t       518.8 ns/op\t     200 B/op\t       8 allocs/op\nBenchmarkToKebab\nBenchmarkToKebab-10                       \t 2333046\t       513.7 ns/op\t     200 B/op\t       8 allocs/op\nBenchmarkToScreamingKebab\nBenchmarkToScreamingKebab-10              \t 2274729\t       521.3 ns/op\t     200 B/op\t       8 allocs/op\nBenchmarkToDotNotation\nBenchmarkToDotNotation-10                 \t 2319278\t       511.0 ns/op\t     200 B/op\t       8 allocs/op\nBenchmarkToScreamingDotNotation\nBenchmarkToScreamingDotNotation-10        \t 2310217\t       518.5 ns/op\t     200 B/op\t       8 allocs/op\n```\n\n## License\n\nMIT\n","funding_links":[],"categories":["Miscellaneous","Go","杂项","Microsoft Office"],"sub_categories":["Strings","字符串"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchanced%2Fcaps","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fchanced%2Fcaps","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fchanced%2Fcaps/lists"}