{"id":13747326,"url":"https://github.com/piotrmurach/strings","last_synced_at":"2025-06-12T13:09:25.696Z","repository":{"id":27250137,"uuid":"112795913","full_name":"piotrmurach/strings","owner":"piotrmurach","description":"A set of useful functions for transforming strings.","archived":false,"fork":false,"pushed_at":"2024-03-09T11:12:34.000Z","size":157,"stargazers_count":129,"open_issues_count":4,"forks_count":12,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-06-01T15:46:57.092Z","etag":null,"topics":["align","alignment","ansi","fold","indent","padding","ruby","strings","text","text-wrap","transform","truncate","wrap"],"latest_commit_sha":null,"homepage":null,"language":"Ruby","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/piotrmurach.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"piotrmurach"}},"created_at":"2017-12-01T23:12:58.000Z","updated_at":"2025-04-19T06:40:03.000Z","dependencies_parsed_at":"2024-06-18T14:13:15.333Z","dependency_job_id":null,"html_url":"https://github.com/piotrmurach/strings","commit_stats":{"total_commits":160,"total_committers":11,"mean_commits":"14.545454545454545","dds":0.06874999999999998,"last_synced_commit":"48a10658a504ca2a42b7e07bc9c05708365f7793"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/piotrmurach/strings","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piotrmurach%2Fstrings","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piotrmurach%2Fstrings/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piotrmurach%2Fstrings/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piotrmurach%2Fstrings/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/piotrmurach","download_url":"https://codeload.github.com/piotrmurach/strings/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/piotrmurach%2Fstrings/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259470951,"owners_count":22862999,"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":["align","alignment","ansi","fold","indent","padding","ruby","strings","text","text-wrap","transform","truncate","wrap"],"created_at":"2024-08-03T06:01:25.205Z","updated_at":"2025-06-12T13:09:25.644Z","avatar_url":"https://github.com/piotrmurach.png","language":"Ruby","readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg width=\"225\" src=\"https://github.com/piotrmurach/strings/blob/master/assets/strings_logo.png\" alt=\"strings logo\" /\u003e\n\u003c/div\u003e\n\n# Strings\n\n[![Gem Version](https://badge.fury.io/rb/strings.svg)][gem]\n[![Actions CI](https://github.com/piotrmurach/strings/workflows/CI/badge.svg?branch=master)][gh_actions_ci]\n[![Build status](https://ci.appveyor.com/api/projects/status/e11tn1fgjwnfwp3r?svg=true)][appveyor]\n[![Maintainability](https://api.codeclimate.com/v1/badges/4ca50e480f42af80678e/maintainability)][codeclimate]\n[![Coverage Status](https://coveralls.io/repos/github/piotrmurach/strings/badge.svg?branch=master)][coverage]\n[![Inline docs](http://inch-ci.org/github/piotrmurach/strings.svg?branch=master)][inchpages]\n\n[gem]: http://badge.fury.io/rb/strings\n[gh_actions_ci]: https://github.com/piotrmurach/strings/actions?query=workflow%3ACI\n[appveyor]: https://ci.appveyor.com/project/piotrmurach/strings\n[codeclimate]: https://codeclimate.com/github/piotrmurach/strings/maintainability\n[coverage]: https://coveralls.io/github/piotrmurach/strings?branch=master\n[inchpages]: http://inch-ci.org/github/piotrmurach/strings\n\n\u003e A set of useful methods for working with strings such as align, truncate, wrap, and many more.\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'strings'\n```\n\nAnd then execute:\n\n    $ bundle\n\nOr install it yourself as:\n\n    $ gem install strings\n\n## Features\n\n* No monkey-patching String class\n* Functional API that can be easily wrapped by other objects\n* Supports multibyte character encodings such as UTF-8, EUC-JP\n* Handles languages without white-spaces between words (like Chinese and Japanese)\n* Supports ANSI escape codes\n* Flexible by nature, split into [components](#4-components)\n\n## Contents\n\n* [1. Usage](#1-usage)\n* [2. API](#2-api)\n  * [2.1 align](#21-align)\n  * [2.2 ansi?](#22-ansi)\n  * [2.3 fold](#23-fold)\n  * [2.4 pad](#24-pad)\n  * [2.5 sanitize](#25-sanitize)\n  * [2.6 truncate](#26-truncate)\n  * [2.7 wrap](#27-wrap)\n* [3. Extending String class](#3-extending-string-class)\n* [4. Components](#4-components)\n\n## 1. Usage\n\n**Strings** is a module with stateless function calls which can be executed directly or mixed into other classes.\n\nFor example, to wrap a text using [wrap](#22-wrap) method, you can call it directly:\n\n```ruby\ntext = \"Think not, is my eleventh commandment; and sleep when you can, is my twelfth.\"\nStrings.wrap(text, 30)\n# =\u003e\n#  \"Think not, is my eleventh\\n\"\n#  \"commandment; and sleep when\\n\"\n#  \"you can, is my twelfth.\"\n```\n\nor using namespaced name:\n\n```ruby\nStrings::Wrap.wrap(text, 30)\n```\n\n## 2. API\n\n### 2.1 align\n\nTo align a given multiline text within a given `width` use `align`, `align_left`, `align_center` or `align_right`.\n\nGiven the following multiline text:\n\n```ruby\ntext = \u003c\u003c-TEXT\nfor there is no folly of the beast\nof the earth which\nis not infinitely\noutdone by the madness of men\nTEXT\n```\n\nPassing `text` as first argument, the maximum width and `:direction` to align to:\n\n```ruby\nStrings.align(text, 40, direction: :center)\n# =\u003e\n#  \"   for there is no folly of the beast   \\n\"\n#  \"           of the earth which           \\n\"\n#  \"           is not infinitely            \\n\"\n#  \"     outdone by the madness of men      \"\n```\n\nYou can also pass `:fill` option to replace default space character:\n\n```ruby\nStrings.align(text, 40, direction: :center, fill: '*')\n# =\u003e\n#  \"***for there is no folly of the beast***\\n\"\n#  \"***********of the earth which***********\\n\"\n#  \"***********is not infinitely************\\n\"\n#  \"*****outdone by the madness of men******\"\n```\n\nIt handles `UTF-8` text:\n\n```ruby\ntext = \"ラドクリフ\\n、マラソン五輪\\n代表に1万m出\\n場にも含み\"\nStrings.align_left(text, 20)\n# =\u003e\n#  \"ラドクリフ          \\n\"\n#  \"、マラソン五輪      \\n\"\n#  \"代表に1万m出        \\n\"\n#  \"場にも含み          \\n\"\n```\n\n### 2.2 ansi?\n\nTo check if a string includes ANSI escape codes use `ansi?` method like so:\n\n```ruby\nStrings.ansi?(\"\\e[33;44mfoo\\e[0m\")\n# =\u003e true\n```\n\nOr fully qualified name:\n\n```ruby\nStrings::ANSI.ansi?(\"\\e[33;44mfoo\\e[0m\")\n# =\u003e true\n```\n\n### 2.3 fold\n\nTo fold a multiline text into a single line preserving white-space characters use `fold`:\n\n```ruby\nStrings.fold(\"\\tfoo \\r\\n\\n bar\")\n# =\u003e \"foo  bar\"\n```\n\n### 2.4 pad\n\nTo pad around a text with a given padding use `pad` function where the seconds argument is a padding value that needs to be one of the following values corresponding with CSS padding property:\n\n```ruby\n[1,1,1,1]  # =\u003e pad text left \u0026 right with 1 character and add 1 line above \u0026 below\n[1,2]      # =\u003e pad text left \u0026 right with 2 characters and add 1 line above \u0026 below\n1          # =\u003e shorthand for [1,1,1,1]\n```\n\nFor example, to pad sentence with a padding of 1 space:\n\n```ruby\ntext = \"Ignorance is the parent of fear.\"\nStrings.pad(text, 1)\n# =\u003e\n#  \"                                  \\n\"\n#  \" Ignorance is the parent of fear. \\n\"\n#  \"                                  \"\n```\n\nYou can also pass `:fill` option to replace default space character:\n\n```ruby\ntext = \"Ignorance is the parent of fear.\"\nStrings.pad(text, [1, 2], fill: \"*\")\n# =\u003e\n#  \"************************************\\n\"\n#  \"**Ignorance is the parent of fear.**\\n\"\n#  \"************************************\"\n```\n\nYou can also apply padding to multiline content:\n\n```ruby\ntext = \u003c\u003c-TEXT\nIt is the easiest thing\nin the world for a man\nto look as if he had\na great secret in him.\nTEXT\n\nStrings.pad(text, 1)\n# =\u003e\n#  \"                         \\n\"\n#  \" It is the easiest thing \\n\"\n#  \" in the world for a man \\n\"\n#  \" to look as if he had \\n\"\n#  \" a great secret in him. \\n\"\n#  \"                         \"\n```\n\nThe `pad` handles `UTF-8` text as well:\n\n```ruby\ntext = \"ラドクリフ、マラソン\"\nStrings.pad(text, 1)\n# =\u003e\n# \"                      \\n\"\n# \" ラドクリフ、マラソン \\n\"\n# \"                      \"\n```\n\n### 2.5 sanitize\n\nTo remove ANSI escape codes from a string use `sanitize`:\n\n```ruby\nStrings.sanitize(\"\\e[33;44mfoo\\e[0m\")\n# =\u003e \"foo\"\n```\n\nor namespaced:\n\n```ruby\nStrings::ANSI.sanitize(\"\\e[33;44mfoo\\e[0m\")\n# =\u003e \"foo\"\n```\n\n### 2.6 truncate\n\nPlease note this API will change in the next release and will be replaced by the `strings-truncation` component. See the [Components](#4-components) section for more information.\n\nYou can truncate a given text after a given length with `truncate` method.\n\nGiven the following text:\n\n```ruby\ntext = \"for there is no folly of the beast of the earth \" +\n       \"which is not infinitely outdone by the madness of men\"\n```\n\nTo shorten the text to given length call `truncate`:\n\n```ruby\nStrings.truncate(text, 20) # =\u003e \"for there is no fol…\"\n```\n\nor directly using the module namesapce:\n\n```ruby\nStrings::Truncate.truncate(text, 20) # =\u003e \"for there is no fol…\"\n```\n\nIf you want to split words on their boundaries use `:separator` option:\n\n```ruby\nStrings.truncate(text, 20, separator: ' ') # =\u003e \"for there is no…\"\n```\n\nUse `:trailing` option (by default `…`) to provide omission characters:\n\n```ruby\nStrings.truncate(text, 22, trailing: '... (see more)')\n# =\u003e \"for there...(see more)\"\n```\n\nYou can also specify `UTF-8` text as well:\n\n```ruby\ntext = 'ラドクリフ、マラソン五輪代表に1万m出場にも含み'\nStrings.truncate(text, 12)   # =\u003e \"ラドクリフ…\"\n```\n\n**Strings::Truncate** works with ANSI escape codes:\n\n```ruby\ntext = \"I try \\e[34mall things\\e[0m, I achieve what I can\"\nStrings.truncate(text, 18)\n# =\u003e \"I try \\e[34mall things\\e[0m…\"\n```\n\n### 2.7 wrap\n\nTo wrap text into lines no longer than `wrap_at` argument length, the `wrap` method will break either on white-space character or in case of east Asian characters on character boundaries.\n\nGiven the following text:\n\n```ruby\ntext = \"Think not, is my eleventh commandment; and sleep when you can, is my twelfth.\"\n```\n\nThen to wrap the text to given length do:\n\n```ruby\nStrings.wrap(text, 30)\n# =\u003e\n#  \"Think not, is my eleventh\\n\"\n#  \"commandment; and sleep when\\n\"\n#  \"you can, is my twelfth.\"\n```\n\nSimilarly, to handle `UTF-8` text do:\n\n```ruby\ntext = \"ラドクリフ、マラソン五輪代表に1万m出場にも含み\"\nStrings.wrap(text, 8)\n# =\u003e\n#  \"ラドクリ\\n\"\n#  \"フ、マラ\\n\"\n#  \"ソン五輪\\n\"\n#  \"代表に1\\n\"\n#  \"万m出場\\n\"\n#  \"にも含み\"\n```\n\n**Strings::Wrap** knows how to handle ANSI codes:\n\n```ruby\nansi_text = \"\\e[32;44mIgnorance is the parent of fear.\\e[0m\"\nStrings.wrap(ansi_text, 14)\n# =\u003e\n#  \"\\e[32;44mIgnorance is \\e[0m\\n\"\n#  \"\\e[32;44mthe parent of \\e[0m\\n\"\n#  \"\\e[32;44mfear.\\e[0m\"\n```\n\nYou can also call `wrap` directly on **Strings::Wrap**:\n\n```ruby\nStrings::Wrap.wrap(text, wrap_at)\n```\n\n## 3. Extending String class\n\nThough it is highly discouraged to pollute core Ruby classes, you can add the required methods to `String` class by using refinements.\n\nFor example, if you wish to only extend strings with `wrap` method do:\n\n```ruby\nmodule MyStringExt\n  refine String do\n    def wrap(*args)\n      Strings.wrap(self, *args)\n    end\n  end\nend\n```\n\nThen `wrap` method will be available for any strings where refinement is applied:\n\n```ruby\nusing MyStringExt\n\nstring.wrap(30)\n```\n\nHowever, if you want to include all the **Strings** methods:\n\n```ruby\nrequire 'strings/extensions'\n\nusing Strings::Extensions\n```\n\n## 4. Components\n\n**Strings** aims to be flexible and allow you to choose only the components that you need. Currently you can choose from:\n\n|  Component   | Description | API docs |\n| ------------ | ----------- | -------- |\n| [strings-ansi](https://github.com/piotrmurach/strings-ansi) | Handle ANSI escape codes in strings. | [docs](https://www.rubydoc.info/gems/strings-ansi) |\n| [strings-case](https://github.com/piotrmurach/strings-case) | Handle case transformations in strings. | [docs](https://www.rubydoc.info/gems/strings-case) |\n| [strings-inflection](https://github.com/piotrmurach/strings-inflection) | Inflects English nouns and verbs. | [docs](https://www.rubydoc.info/gems/strings-inflection) |\n| [strings-numeral](https://github.com/piotrmurach/strings-numeral) | Express numbers as word numerals. | [docs](https://www.rubydoc.info/gems/strings-numeral) |\n| [strings-truncation](https://github.com/piotrmurach/strings-truncation) | Truncate strings with fullwidth characters and ANSI codes. | [docs](https://www.rubydoc.info/gems/strings-truncation) |\n\n## Development\n\nAfter checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.\n\nTo install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at https://github.com/piotrmurach/strings. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.\n\n1. Fork it ( https://github.com/piotrmurach/strings/fork )\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am 'Add some feature'`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Create a new Pull Request\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).\n\n## Code of Conduct\n\nEveryone interacting in the Strings project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/piotrmurach/strings/blob/master/CODE_OF_CONDUCT.md).\n\n## Copyright\n\nCopyright (c) 2017 Piotr Murach. See LICENSE for further details.\n","funding_links":["https://github.com/sponsors/piotrmurach"],"categories":["Ruby"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpiotrmurach%2Fstrings","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpiotrmurach%2Fstrings","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpiotrmurach%2Fstrings/lists"}