Utility.Text (Portico/Z v0.1.0)

Functions to generate, modify, and generally fiddle with text values.

Link to this section Summary

Functions

Split a String containing "hashtags" into a List of individual tags.

Convert a string to snake_case.

Truncate a String to a given length.

Encode data into a single value which can be passed in a URL without it being immediately obvious what that value is.

Decode concealed data from url_conceal/1.

Link to this section Functions

Link to this function

parse_hashtags(str)

Split a String containing "hashtags" into a List of individual tags.

Rules

Use a (space) or a , to separate tags:

"TagOne TagTwo TagThree"
# ...is the same as
"TagOne, TagTwo, TagThree"

Adding a # (hash) to the beginning of a tag works, but is optional:

"#Space #Rockets #OhMyGosh"
# ...is the same as
"Space Rockets OhMyGosh"

Items in snake_case or kebab-case will be converted to CamelCase:

"#tom-brady #foot_ball #sports #opinions"
# ... is the same as
"#TomBrady #FootBall #Sports #Opinions"

Examples

iex> "#PerformingArts #Music #Flute"
...> |> Utility.Text.parse_hashtags()
["PerformingArts", "Music", "Flute"]

iex> "#wonder-boys #michael_douglas #film"
...> |> Utility.Text.parse_hashtags()
["WonderBoys", "MichaelDouglas", "Film"]

iex> "aviation, amelia-earhardt, ocean" 
...> |> Utility.Text.parse_hashtags()
["Aviation", "AmeliaEarhardt", "Ocean"]

iex> "#canal, big ship, #stuck" 
...> |> Utility.Text.parse_hashtags()
["Canal", "Big", "Ship", "Stuck"]

iex> "just a pile of words" 
...> |> Utility.Text.parse_hashtags()
["Just", "A", "Pile", "Of", "Words"]

iex> "#OMG #Wut #LOLled" 
...> |> Utility.Text.parse_hashtags()
["OMG", "Wut", "LOLled"]

iex> "#redundancy #redundancy #redundancy" 
...> |> Utility.Text.parse_hashtags()
["Redundancy"]

iex> Utility.Text.parse_hashtags(42)
[]

iex> Utility.Text.parse_hashtags(nil)
[]

See also Utility.Collections.to_hashtags/1

Link to this function

snake_case(str)

Convert a string to snake_case.

Has a few other behaviours that are worth noting:

  • Replaces spaces with underscores
  • Replaces multiple underscores with one underscore
  • Converts CamelCase to snake_case (converts capital letters to lower+underscore)
  • Deletes random characters (non-alphanumeric)

Examples

iex> Utility.Text.snake_case("SomeThing")
"some_thing"

iex> Utility.Text.snake_case("some Thing")
"some_thing"

iex> Utility.Text.snake_case("Some__ _ Thing")
"some_thing"

iex> Utility.Text.snake_case("some thing is great")
"some_thing_is_great"

iex> Utility.Text.snake_case("Random @#$% Characters")
"random_characters"

iex> Utility.Text.snake_case("background-color")
"background_color"

By the way, we didn't make a camel_case because Macro.camelize/1 works very well!

Link to this function

truncate(str, len, opts \\ [])

Specs

truncate(str :: String.t(), len :: integer(), opts :: Keyword.t()) :: String.t()

Truncate a String to a given length.

Options

You can pass the following opts:

  • :ellipsis (Boolean). Append ellipses to the end for a total character count of length, if the truncated length is less than len. Defaults to false

Examples

iex> Utility.Text.truncate("abcdefghijklmnopqrstuvwxyz", 10)
"abcdefghij"

iex> Utility.Text.truncate("abcdefghizklmnopqrstuvwxyz", 10, ellipsis: true)
"abcdefg..."

iex> Utility.Text.truncate("short", 20, ellipsis: true)
"short"

iex> Utility.Text.truncate("short", 5, ellipsis: true)
"short"
Link to this function

url_conceal(data)

Specs

url_conceal(map() | list()) :: String.t()
url_conceal(String.t()) :: String.t()

Encode data into a single value which can be passed in a URL without it being immediately obvious what that value is.

We use this often in URLS that families will see, not as a security measure, but to keep URLS nice and tight without having to worry about formatting issues brought about with JSON or other data values. Base64 (when it's URL-safe) is understood by everything, and it's also possible to decode Base64 from any programming language paradigm (including Javascript in the browser), which is handy when we pass these values to external systems.

As a convenience, maps and lists will be converted to JSON strings before being obfuscated.

See url_reveal/1 for the converse of this function.

Examples

iex> Text.url_conceal("some data")
"c29tZSBkYXRh"

iex> Text.url_conceal(~s({"some": "json"}))
"eyJzb21lIjogImpzb24ifQ=="

iex> Text.url_conceal(%{some: "map"})
"eyJzb21lIjoibWFwIn0="

iex> Text.url_conceal(["some", "list"])
"WyJzb21lIiwibGlzdCJd"
Link to this function

url_reveal(string)

Specs

url_reveal(String.t()) :: term()

Decode concealed data from url_conceal/1.

An attempt will be made to parse the result in case it's JSON, but the result will be returned un-modified if JSON parsing fails.

Returns :error in the case that you send an un-parseable (not properly concealed) value.

Examples

(see url_conceal/1 for the converse of these examples).

iex> Text.url_reveal("not concealed")
:error

iex> Text.url_reveal("c29tZSBkYXRh")
"some data"

iex> Text.url_reveal("eyJzb21lIjogImpzb24ifQ==")
%{"some" => "json"}

iex> Text.url_reveal("eyJzb21lIjoibWFwIn0=")
%{"some" => "map"}

iex> Text.url_reveal("WyJzb21lIiwibGlzdCJd")
["some", "list"]