Skip to content

Commit

Permalink
Version number comparison & fix chained version renames (#134)
Browse files Browse the repository at this point in the history
* Prepare possibility to get version as tuple

* Compare bitstyles versions numerically

* Add dummy example of chained class renames

* Chain class renames

* Mix credo warnings

* Create two separate 'version' functions

* Credo warnings

* Add Changelog entry

* Extract Bitstyles.Version

* Do not skip versions with noop downgrades

* Do not include version test classes in prod

* I forgot version 3.1.0

* Update lib/bitstyles_phoenix/bitstyles.ex

Co-authored-by: Andreas Knöpfle <[email protected]>

* Fix format

---------

Co-authored-by: Andreas Knöpfle <[email protected]>
  • Loading branch information
angelikatyborska and andreasknoepfle authored Sep 23, 2024
1 parent 2859e4c commit c101a50
Show file tree
Hide file tree
Showing 11 changed files with 338 additions and 213 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## Unreleased

- Switched bitstyles version comparisons from string comparisons to tuple comparisons, which will ensure correct output if bitstyles version ever contains a number above 9.
- Modified the process of downgrading classnames to the target bitstyles version by chaining renames. This is necessary preparation work to support bitstyles 6.0.0.

## v2.4.0 - 2024-07-18

- Added support for phoenix_html `v4`. You can also continue using phoenix_html `v3`. To replace `Phoenix.HTML.Form` input helpers removed in phoenix_html `v4`, new components `ui_raw_input` and `ui_raw_label` were added.
Expand Down
4 changes: 4 additions & 0 deletions config/config.exs
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,7 @@ config :bitstyles_phoenix,
trim_e2e_classes: [enabled: true]

config :phoenix, :json_library, Jason

if config_env() === :test do
config :bitstyles_phoenix, add_version_test_classes: true
end
4 changes: 2 additions & 2 deletions docs/bitstyles_version_compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ open version_showcase/index.html

```elixir
def ui_tricky_component(assigns) do
version = BitstylesPhoenix.Bitstyles.version()
version = BitstylesPhoenix.Bitstyles.Version.version()

if version >= "5.0.0" do
if version >= {5,0,0} do
~H"""
<p class={classnames("u-new-class-that-does-everything")}>...</p>
"""
Expand Down
2 changes: 1 addition & 1 deletion lib/bitstyles_phoenix.ex
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ defmodule BitstylesPhoenix do
### Bitstyles version
BitstylesPhoenix will generate classes #{BitstylesPhoenix.Bitstyles.version()} of bitstyles.
BitstylesPhoenix will generate classes #{BitstylesPhoenix.Bitstyles.Version.version_string()} of bitstyles.
You can set older versions with a configuration:
```elixir
Expand Down
119 changes: 85 additions & 34 deletions lib/bitstyles_phoenix/bitstyles.ex
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
defmodule BitstylesPhoenix.Bitstyles do
@moduledoc false

@default_version "5.0.1"
require BitstylesPhoenix.Bitstyles.Version
alias BitstylesPhoenix.Bitstyles.Version

@cdn_url "https://cdn.jsdelivr.net/npm/bitstyles"

def cdn_url do
"#{@cdn_url}@#{version()}"
"#{@cdn_url}@#{Version.version_string()}"
end

@doc """
Returns the classnames for the configured version.
Input classnames are assumed to be from the #{@default_version} version of bitstyles.
Input classnames are assumed to be from the #{Version.default_version_string()} version of bitstyles.
"""
def classname(name), do: classname(name, version())
def classname(name), do: classname(name, Version.version())

def classname(class, version) when version > "5.0.1" do
IO.warn("Version #{version} of bitstyles is not yet supported")
class
def classname(class, version) when is_tuple(version) do
downgrade_classname(class, version, Version.default_version())
end

# Note about class renaming:
Expand All @@ -25,11 +26,24 @@ defmodule BitstylesPhoenix.Bitstyles do
# If it does exist, then doing this renaming in the classname/2 function would make it impossible
# for users of older bitstyles to use the "class-name-A" classname.

def classname(class, version) when version >= "5.0.0" do
defp downgrade_classname(class, target_version, _current_version)
when target_version > {5, 0, 1} do
IO.warn("Version #{Version.to_string(target_version)} of bitstyles is not yet supported")
class
end

defp downgrade_classname(class, target_version, current_version)
when target_version == current_version do
class
end

def classname(class, version) when version >= "4.2.0" do
defp downgrade_classname(class, target_version, {5, 0, 1}) do
# no changes when downgrading 5.0.1 -> 5.0.0
downgrade_classname(class, target_version, {5, 0, 0})
end

defp downgrade_classname(class, target_version, {5, 0, 0}) do
# downgrading 5.0.0 -> 4.3.0
sizes_renaming = %{
"3xs" => "xxxs",
"2xs" => "xxs",
Expand Down Expand Up @@ -66,23 +80,36 @@ defmodule BitstylesPhoenix.Bitstyles do
class -> class
end

classname(class, "5.0.0")
class = test_only_downgrade(class, "u-version-5-0-0", "u-version-4")

downgrade_classname(class, target_version, {4, 3, 0})
end

def classname(class, version) when version >= "4.0.0" do
mapping =
defp downgrade_classname(class, target_version, {4, 3, 0}) do
# no changes when downgrading from 4.3.0 -> 4.2.0
downgrade_classname(class, target_version, {4, 2, 0})
end

defp downgrade_classname(class, target_version, {4, 2, 0}) do
# downgrading from 4.2.0 -> 4.1.0
class =
case class do
"u-border-radius-" <> variant -> "u-round-#{variant}"
_ -> class
end

classname(mapping, "4.3.0")
downgrade_classname(class, target_version, {4, 1, 0})
end

def classname(class, version) when version >= "2.0.0" do
# credo:disable-for-previous-line Credo.Check.Refactor.CyclomaticComplexity
defp downgrade_classname(class, target_version, {4, 1, 0}) do
# no changes when downgrading from 4.1.0 -> 4.0.0
downgrade_classname(class, target_version, {4, 0, 0})
end

mapping =
# credo:disable-for-next-line Credo.Check.Refactor.CyclomaticComplexity
defp downgrade_classname(class, target_version, {4, 0, 0}) do
# downgrading from 4.0.0 -> 3.0.0
class =
case class do
# Make sure that we leave the classes in place that are old anyway (update compatibility)
"u-bg--" <> _ -> class
Expand All @@ -104,11 +131,24 @@ defmodule BitstylesPhoenix.Bitstyles do
_ -> class
end

classname(mapping, "4.0.0")
class = test_only_downgrade(class, "u-version-4", "u-version-2")

downgrade_classname(class, target_version, {3, 1, 0})
end

def classname(class, version) when version >= "1.5.0" do
mapping =
defp downgrade_classname(class, target_version, {3, 1, 0}) do
# no changes when downgrading from 3.1.0 -> 3.0.0
downgrade_classname(class, target_version, {3, 0, 0})
end

defp downgrade_classname(class, target_version, {3, 0, 0}) do
# no changes when downgrading from 3.0.0 -> 2.0.0
downgrade_classname(class, target_version, {2, 0, 0})
end

defp downgrade_classname(class, target_version, {2, 0, 0}) do
# downgrading 2.0.0 -> 1.5.0
class =
case class do
"u-flex-shrink-" <> number -> "u-flex__shrink-#{number}"
"u-flex-grow-" <> number -> "u-flex__grow-#{number}"
Expand All @@ -117,36 +157,47 @@ defmodule BitstylesPhoenix.Bitstyles do
_ -> class
end

classname(mapping, "2.0.0")
class = test_only_downgrade(class, "u-version-2", "u-version-1-4")

downgrade_classname(class, target_version, {1, 5, 0})
end

defp downgrade_classname(class, target_version, {1, 5, 0}) do
# no changes when downgrading from 1.5.0 -> 1.4.0
downgrade_classname(class, target_version, {1, 4, 0})
end

def classname(class, version) when version >= "1.3.0" do
mapping =
defp downgrade_classname(class, target_version, {1, 4, 0}) do
# downgrading 1.4.0 -> 1.3.0
class =
case class do
"u-grid-cols-" <> number -> "u-grid--#{number}-col"
"u-col-span-" <> number -> "u-grid__col-span-#{number}"
"u-col-start-" <> number -> "u-grid__col-#{number}"
_ -> class
end

classname(mapping, "1.5.0")
class = test_only_downgrade(class, "u-version-1-4", "u-version-1-3")

downgrade_classname(class, target_version, {1, 3, 0})
end

defp downgrade_classname(class, target_version, {1, 3, 0}) do
# no changes when downgrading from 1.3.0 -> 1.2.0
downgrade_classname(class, target_version, {1, 2, 0})
end

def classname(_class, version) do
defp downgrade_classname(_class, target_version, {1, 2, 0}) do
raise("""
The version #{version} of bitstyles is not supported. The helpers will produce incorrect classes.
The version #{Version.to_string(target_version)} of bitstyles is not supported. The helpers will produce incorrect classes.
Please upgrade bitsyles and set the `bitsyles_version` to the updated version.
""")
end

def version do
bitstyles_version_override = Process.get(:bitstyles_phoenix_bistyles_version)

bitstyles_version_override ||
Application.get_env(:bitstyles_phoenix, :bitstyles_version, @default_version)
end

def default_version do
@default_version
if Application.compile_env(:bitstyles_phoenix, :add_version_test_classes, false) do
defp test_only_downgrade(from, from, to), do: to
defp test_only_downgrade(class, _, _), do: class
else
defp test_only_downgrade(class, _, _), do: class
end
end
39 changes: 39 additions & 0 deletions lib/bitstyles_phoenix/bitstyles/version.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
defmodule BitstylesPhoenix.Bitstyles.Version do
@moduledoc false

@default_version "5.0.1"

def version do
to_tuple(version_string())
end

def version_string do
bitstyles_version_override = Process.get(:bitstyles_phoenix_bistyles_version)

bitstyles_version_override ||
Application.get_env(:bitstyles_phoenix, :bitstyles_version, @default_version)
end

def default_version do
to_tuple(@default_version)
end

def default_version_string, do: @default_version

def to_tuple(version) when is_tuple(version), do: version

def to_tuple(version) when is_binary(version) do
version
|> String.split(".")
|> Enum.map(&String.to_integer/1)
|> List.to_tuple()
end

def to_string(version) when is_binary(version), do: version

def to_string(version) when is_tuple(version) do
version
|> Tuple.to_list()
|> Enum.map_join(".", &Kernel.to_string/1)
end
end
6 changes: 3 additions & 3 deletions lib/bitstyles_phoenix/component/button.ex
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ defmodule BitstylesPhoenix.Component.Button do
extra = assigns_to_attributes(assigns, [:icon, :class, :color, :shape, :variant])

assigns =
if Bitstyles.version() >= "5.0.0" && assigns[:variant] do
if Bitstyles.Version.version() >= {5, 0, 0} && assigns[:variant] do
IO.warn("Attribute `variant` is deprecated in ui_button/1! Change to `color` and `shape`")

assigns
Expand All @@ -298,7 +298,7 @@ defmodule BitstylesPhoenix.Component.Button do
end

classes =
if Bitstyles.version() >= "5.0.0" do
if Bitstyles.Version.version() >= {5, 0, 0} do
color_and_shape_classes(assigns[:color], assigns[:shape])
else
variant_classes(assigns[:variant])
Expand Down Expand Up @@ -538,7 +538,7 @@ defmodule BitstylesPhoenix.Component.Button do
extra = assigns_to_attributes(assigns, [:icon, :label, :reversed, :color, :title])

extra =
if Bitstyles.version() >= "5.0.0" do
if Bitstyles.Version.version() >= {5, 0, 0} do
if assigns[:reversed] do
Keyword.put_new(extra, :"data-theme", "dark")
else
Expand Down
2 changes: 1 addition & 1 deletion lib/bitstyles_phoenix/component/description_list.ex
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ defmodule BitstylesPhoenix.Component.DescriptionList do

# u-gap-l and u-gap-xl in 5.0.0 are equivalent to respectively u-gap-m and u-gap-l in 4.3.0
gap_class =
if Bitstyles.version() >= "5.0.0" do
if Bitstyles.Version.version() >= {5, 0, 0} do
"u-gap-l"
else
"u-gap-m"
Expand Down
4 changes: 2 additions & 2 deletions lib/bitstyles_phoenix/component/dropdown.ex
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ defmodule BitstylesPhoenix.Component.Dropdown do
assigns_from_single_slot(assigns, :button, exclude: [:label, :icon_file])

button_extra =
if Bitstyles.version() >= "5.0.0" do
if Bitstyles.Version.version() >= {5, 0, 0} do
button_extra
|> Keyword.put_new(:color, :secondary)
else
Expand Down Expand Up @@ -516,7 +516,7 @@ defmodule BitstylesPhoenix.Component.Dropdown do
|> assigns_to_attributes()

extra =
if Bitstyles.version() >= "5.0.0" do
if Bitstyles.Version.version() >= {5, 0, 0} do
extra
|> Keyword.put_new(:shape, "menu")
|> Keyword.put_new(:color, "transparent")
Expand Down
4 changes: 3 additions & 1 deletion lib/bitstyles_phoenix/showcase.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ defmodule BitstylesPhoenix.Showcase do
alias Phoenix.HTML.Safe

defmacro story(name, doctest_iex_code, doctest_expected_results, opts \\ []) do
default_version = BitstylesPhoenix.Bitstyles.default_version() |> String.to_atom()
default_version =
BitstylesPhoenix.Bitstyles.Version.default_version_string()
|> String.to_atom()

doctest_expected_results =
if is_list(doctest_expected_results) && is_tuple(List.first(doctest_expected_results)) do
Expand Down
Loading

0 comments on commit c101a50

Please sign in to comment.