Fix edge cases with parser

- Remove front_matter dependency, and use a hand-rolled simpler parser
  which is suitable for the data to parse (which is well-formed).
- Fix a couple of edge cases with years and titles with commas
This commit is contained in:
Claudio Ortolina
2024-09-14 14:09:28 +01:00
parent 2c42f3ea32
commit 170f195aae
4 changed files with 72 additions and 10 deletions
+30 -5
View File
@@ -1,24 +1,49 @@
defmodule MusicLibrary.Records.Parser do
alias MusicLibrary.Records.Record
def from_entry_contents(entry_contents) do
with {:ok, meta, _body} <- FrontMatter.parse(entry_contents) do
with {:ok, [meta]} <- parse_frontmatter(entry_contents) do
{:ok,
%Record{
%{
type: parse_subtype(meta["subType"]),
musicbrainz_id: meta["id"],
title: meta["title"],
year: meta["year"],
year: meta["year"] |> maybe_parse_year(),
image: meta["image"],
genres: meta["genres"]
}}
end
end
defp parse_frontmatter(entry_contents) do
case entry_contents do
"---\n" <> rest ->
case String.split(rest, "\n---\n") do
[frontmatter, _] ->
case YamlElixir.read_all_from_string(frontmatter) do
{:ok, meta} -> {:ok, meta}
{:error, _} -> {:error, "Invalid frontmatter"}
end
_ ->
{:error, "Invalid frontmatter"}
end
_ ->
{:error, "Invalid frontmatter"}
end
end
defp parse_subtype("Album"), do: :album
defp parse_subtype("ep"), do: :ep
defp parse_subtype("Live"), do: :live
defp parse_subtype("Compilation"), do: :compilation
defp parse_subtype("Single"), do: :single
defp parse_subtype(_), do: :other
defp maybe_parse_year(nil), do: nil
defp maybe_parse_year(year) when is_integer(year), do: year
defp maybe_parse_year(year) when is_binary(year) do
{integer, _remainder} = Integer.parse(year, 10)
integer
end
end
+1 -1
View File
@@ -38,7 +38,7 @@ defmodule MusicLibrary.MixProject do
{:ecto_sqlite3, ">= 0.0.0"},
{:phoenix_html, "~> 4.1"},
{:phoenix_live_reload, "~> 1.2", only: :dev},
{:front_matter, "~> 1.0"},
{:yaml_elixir, "~> 2.11"},
# TODO bump on release to {:phoenix_live_view, "~> 1.0.0"},
{:phoenix_live_view, "~> 1.0.0-rc.1", override: true},
{:floki, ">= 0.30.0", only: :test},
+1 -2
View File
@@ -14,7 +14,6 @@
"exqlite": {:hex, :exqlite, "0.23.0", "6e851c937a033299d0784994c66da24845415072adbc455a337e20087bce9033", [:make, :mix], [{:cc_precompiler, "~> 0.1", [hex: :cc_precompiler, repo: "hexpm", optional: false]}, {:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.8", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "404341cceec5e6466aaed160cf0b58be2019b60af82588c215e1224ebd3ec831"},
"file_system": {:hex, :file_system, "1.0.1", "79e8ceaddb0416f8b8cd02a0127bdbababe7bf4a23d2a395b983c1f8b3f73edd", [:mix], [], "hexpm", "4414d1f38863ddf9120720cd976fce5bdde8e91d8283353f0e31850fa89feb9e"},
"floki": {:hex, :floki, "0.36.2", "a7da0193538c93f937714a6704369711998a51a6164a222d710ebd54020aa7a3", [:mix], [], "hexpm", "a8766c0bc92f074e5cb36c4f9961982eda84c5d2b8e979ca67f5c268ec8ed580"},
"front_matter": {:hex, :front_matter, "1.0.1", "caca2cb16336e1d82ca5c5e9d94f88fd6d4ce84c1f05253e76d357650d4c46a9", [:mix], [{:yaml_elixir, "~> 2.5.0", [hex: :yaml_elixir, repo: "hexpm", optional: false]}], "hexpm", "1c4daa17c071b245e3706795b98814392fe0ce6bbbfb7c6543be63db86a4e953"},
"gettext": {:hex, :gettext, "0.26.1", "38e14ea5dcf962d1fc9f361b63ea07c0ce715a8ef1f9e82d3dfb8e67e0416715", [:mix], [{:expo, "~> 0.5.1 or ~> 1.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "01ce56f188b9dc28780a52783d6529ad2bc7124f9744e571e1ee4ea88bf08734"},
"heroicons": {:git, "https://github.com/tailwindlabs/heroicons.git", "88ab3a0d790e6a47404cba02800a6b25d2afae50", [tag: "v2.1.1", sparse: "optimized", depth: 1]},
"hpax": {:hex, :hpax, "1.0.0", "28dcf54509fe2152a3d040e4e3df5b265dcb6cb532029ecbacf4ce52caea3fd2", [:mix], [], "hexpm", "7f1314731d711e2ca5fdc7fd361296593fc2542570b3105595bb0bc6d0fad601"},
@@ -38,5 +37,5 @@
"websock": {:hex, :websock, "0.5.3", "2f69a6ebe810328555b6fe5c831a851f485e303a7c8ce6c5f675abeb20ebdadc", [:mix], [], "hexpm", "6105453d7fac22c712ad66fab1d45abdf049868f253cf719b625151460b8b453"},
"websock_adapter": {:hex, :websock_adapter, "0.5.7", "65fa74042530064ef0570b75b43f5c49bb8b235d6515671b3d250022cb8a1f9e", [:mix], [{:bandit, ">= 0.6.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:plug, "~> 1.14", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 2.6", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "d0f478ee64deddfec64b800673fd6e0c8888b079d9f3444dd96d2a98383bdbd1"},
"yamerl": {:hex, :yamerl, "0.10.0", "4ff81fee2f1f6a46f1700c0d880b24d193ddb74bd14ef42cb0bcf46e81ef2f8e", [:rebar3], [], "hexpm", "346adb2963f1051dc837a2364e4acf6eb7d80097c0f53cbdc3046ec8ec4b4e6e"},
"yaml_elixir": {:hex, :yaml_elixir, "2.5.0", "45de762be6d75fa5a8b5f44ddff8c30f64c26526eab5b1d72e36d616007b7796", [:mix], [{:yamerl, "~> 0.7", [hex: :yamerl, repo: "hexpm", optional: false]}], "hexpm", "80fe4e43f05582f2a90f2dcd73fc6171fbd65f2e6836f71fe4ce2154ef358c36"},
"yaml_elixir": {:hex, :yaml_elixir, "2.11.0", "9e9ccd134e861c66b84825a3542a1c22ba33f338d82c07282f4f1f52d847bd50", [:mix], [{:yamerl, "~> 0.10", [hex: :yamerl, repo: "hexpm", optional: false]}], "hexpm", "53cc28357ee7eb952344995787f4bb8cc3cecbf189652236e9b163e8ce1bc242"},
}
+40 -2
View File
@@ -1,6 +1,6 @@
defmodule MusicLibrary.Records.ParserTest do
use ExUnit.Case, async: true
alias MusicLibrary.Records.{Parser, Record}
alias MusicLibrary.Records.Parser
@obsidian_entry_path Path.expand("../../support/fixtures/marillion-marbles.md", __DIR__)
@@ -9,7 +9,7 @@ defmodule MusicLibrary.Records.ParserTest do
assert Parser.from_entry_contents(entry_contents) ==
{:ok,
%Record{
%{
type: :album,
musicbrainz_id: "20790e26-98e4-3ad3-a67f-b674758b942d",
title: "Marbles",
@@ -27,4 +27,42 @@ defmodule MusicLibrary.Records.ParserTest do
]
}}
end
test "handles special characters in titles" do
entry_contents = """
---
type: "musicRelease"
subType: "Album"
title: "Guardians of the Galaxy: Awesome Mix, Vol. 1"
englishTitle: "Guardians of the Galaxy: Awesome Mix, Vol. 1"
year: "2014"
dataSource: "MusicBrainz API"
url: "https://musicbrainz.org/release-group/950092d6-45f6-4269-87da-99a9ff2fcc52"
id: "950092d6-45f6-4269-87da-99a9ff2fcc52"
genres:
- "classic rock"
- "pop"
- "pop rock"
- "rock"
artists:
- "Various Artists"
image: "https://coverartarchive.org/release-group/950092d6-45f6-4269-87da-99a9ff2fcc52/front"
rating: 9.6
personalRating: 0
tags: "mediaDB/music/Album"
---
"""
assert Parser.from_entry_contents(entry_contents) ==
{:ok,
%{
genres: ["classic rock", "pop", "pop rock", "rock"],
image:
"https://coverartarchive.org/release-group/950092d6-45f6-4269-87da-99a9ff2fcc52/front",
musicbrainz_id: "950092d6-45f6-4269-87da-99a9ff2fcc52",
title: "Guardians of the Galaxy: Awesome Mix, Vol. 1",
type: :album,
year: 2014
}}
end
end