fix(style): replace Map.get with dot access and pattern matching where keys are guaranteed (CSM-032)
This commit is contained in:
33
CODESMELL.md
33
CODESMELL.md
@@ -468,10 +468,35 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### CSM-032 — `Map.get` with Default Instead of Pattern Matching
|
### ~~CSM-032 — `Map.get` with Default Instead of Pattern Matching~~ ✅ FIXED
|
||||||
- **Files:** Widespread
|
- **Fixed:** 2026-05-27
|
||||||
- **What:** `Map.get(map, key, default)` when the key is expected to exist.
|
- **What was done:**
|
||||||
- **Fix:** Use pattern matching (`%{key: value} = map`) or `Map.fetch!/2` if the key is required.
|
- **Metadata struct access** — Replaced `Map.get(metadata, :key)` / `Map.get(metadata, :key, default)` with dot access (`metadata.key`) across 10 files that consume the well-defined metadata map from `Metadata.load_state()`:
|
||||||
|
- `lib/bds/posts/translation_validation.ex` — `:main_language`, `:blog_languages`
|
||||||
|
- `lib/bds/posts/auto_translation.ex` — `:main_language`, `:blog_languages`
|
||||||
|
- `lib/bds/desktop/shell_commands.ex` — `:main_language`, `:blog_languages`
|
||||||
|
- `lib/bds/desktop/shell_live/settings_editor/project_settings.ex` — all 10 metadata fields
|
||||||
|
- `lib/bds/desktop/shell_live/settings_editor/style_editor.ex` — `:pico_theme`
|
||||||
|
- `lib/bds/desktop/shell_live/settings_editor/managed_categories.ex` — `:categories`, `:category_settings`
|
||||||
|
- `lib/bds/desktop/shell_live/settings_editor/publishing_settings.ex` — `:publishing_preferences`
|
||||||
|
- `lib/bds/desktop/shell_live/import_editor/taxonomy_editing.ex` — `:categories`
|
||||||
|
- `lib/bds/desktop/shell_live/import_editor/analysis_state.ex` — `:default_author`
|
||||||
|
- `lib/bds/import_execution.ex` — `:default_author`
|
||||||
|
- **Overlay context maps** — Replaced `Map.get(delete_details, :key, default)` and `Map.get(merge, :key, default)` with pattern matching in `lib/bds/desktop/overlay.ex`:
|
||||||
|
- `open(:media, :confirm_delete, ...)` — pattern matches `%{title:, entity_name:, entity_type:, reference_list:}` from `context.delete_details`
|
||||||
|
- `open(:tags, :confirm_merge, ...)` — pattern matches `%{title:, message:}` from `context.merge_details`
|
||||||
|
- `normalize_ai_fields/1` — pattern matches `%{key:, label:, current_value:, suggested_value:, locked:}` from each field
|
||||||
|
- `language_picker/2` — extracts `existing_translations`, `language_names`, `language_flags` into local bindings before the loop, eliminating nested `Map.get(Map.get(...))` calls
|
||||||
|
- **Overlay media/post maps** — Replaced `Map.get(media, :field)` with dot access in `to_insert_media_result`, `to_gallery_image`, `gallery_images`, search filtering, and `to_insert_link_result` (media/post maps are built with known keys by `overlay_components.ex`)
|
||||||
|
- **Generation pipeline** — Replaced `Map.get(post, :field)` with `post.field` for Post struct fields across:
|
||||||
|
- `lib/bds/generation/data.ex` — `:author`, `:tags`, `:categories`, `:template_slug`, `:do_not_translate`, `:language` in `build_published_translation_variant` and `resolve_posts_for_language`
|
||||||
|
- `lib/bds/generation/outputs.ex` — `:language` (all occurrences)
|
||||||
|
- `lib/bds/generation/validation.ex` — `:file_path`
|
||||||
|
- `lib/bds/generation/sitemap.ex` — `:do_not_translate`
|
||||||
|
- `lib/bds/preview.ex` — `:template_slug`
|
||||||
|
- Kept `Map.get` where appropriate: dynamic field access (`Map.get(post, field)` with variable keys), truly optional keys (`:translation_source_slug` on mixed struct/map lists), external data lookups (string-keyed JSON, form params), and hash-map lookups with defaults.
|
||||||
|
- Updated `test/bds/desktop/overlay_test.exs` to provide complete `delete_details` and `merge_details` maps matching the real contract from `overlay_components.ex`.
|
||||||
|
- Added 18 tests in `test/bds/csm032_map_get_pattern_match_test.exs`: source-level assertions that metadata consumers use dot access, overlay uses pattern matching for known structures, and generation pipeline uses dot access for Post struct fields.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -48,29 +48,32 @@ defmodule BDS.Desktop.Overlay do
|
|||||||
end
|
end
|
||||||
|
|
||||||
def open(:media, :confirm_delete, context) do
|
def open(:media, :confirm_delete, context) do
|
||||||
delete_details = Map.get(context, :delete_details, %{})
|
%{
|
||||||
|
title: title,
|
||||||
|
entity_name: entity_name,
|
||||||
|
entity_type: entity_type,
|
||||||
|
reference_list: reference_list
|
||||||
|
} = context.delete_details
|
||||||
|
|
||||||
%{
|
%{
|
||||||
kind: :confirm_delete,
|
kind: :confirm_delete,
|
||||||
title: Map.get(delete_details, :title, "Delete"),
|
title: title,
|
||||||
entity_name: Map.get(delete_details, :entity_name, ""),
|
entity_name: entity_name,
|
||||||
entity_type: Map.get(delete_details, :entity_type, "media"),
|
entity_type: entity_type,
|
||||||
reference_count: length(Map.get(delete_details, :reference_list, [])),
|
reference_count: length(reference_list),
|
||||||
reference_list: Map.get(delete_details, :reference_list, [])
|
reference_list: reference_list
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def open(:tags, :confirm_delete, context), do: open(:media, :confirm_delete, context)
|
def open(:tags, :confirm_delete, context), do: open(:media, :confirm_delete, context)
|
||||||
|
|
||||||
def open(:tags, :confirm_merge, context) do
|
def open(:tags, :confirm_merge, context) do
|
||||||
merge = Map.get(context, :merge_details, %{})
|
%{title: title, message: message} = context.merge_details
|
||||||
target = Map.get(merge, :target, "")
|
|
||||||
count = Map.get(merge, :count, 0)
|
|
||||||
|
|
||||||
%{
|
%{
|
||||||
kind: :confirm_dialog,
|
kind: :confirm_dialog,
|
||||||
title: Map.get(merge, :title, "Merge #{count} tags into #{target}?"),
|
title: title,
|
||||||
message: Map.get(merge, :message, "Cannot be undone.")
|
message: message
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -115,8 +118,8 @@ defmodule BDS.Desktop.Overlay do
|
|||||||
|> Map.get(:all_media, [])
|
|> Map.get(:all_media, [])
|
||||||
|> Enum.filter(fn media ->
|
|> Enum.filter(fn media ->
|
||||||
normalized == "" or
|
normalized == "" or
|
||||||
search_matches?(Map.get(media, :title, ""), normalized) or
|
search_matches?(media.title, normalized) or
|
||||||
search_matches?(Map.get(media, :original_name, ""), normalized)
|
search_matches?(media.original_name, normalized)
|
||||||
end)
|
end)
|
||||||
|> Enum.map(&to_insert_media_result/1)
|
|> Enum.map(&to_insert_media_result/1)
|
||||||
|
|
||||||
@@ -203,18 +206,22 @@ defmodule BDS.Desktop.Overlay do
|
|||||||
def insert_media_result(_overlay, _media_id), do: nil
|
def insert_media_result(_overlay, _media_id), do: nil
|
||||||
|
|
||||||
defp language_picker(context, source_language) do
|
defp language_picker(context, source_language) do
|
||||||
|
existing_translations = Map.get(context, :existing_translations, %{})
|
||||||
|
language_names = Map.get(context, :language_names, %{})
|
||||||
|
language_flags = Map.get(context, :language_flags, %{})
|
||||||
|
|
||||||
targets =
|
targets =
|
||||||
context
|
context
|
||||||
|> Map.get(:blog_languages, [])
|
|> Map.get(:blog_languages, [])
|
||||||
|> Enum.uniq()
|
|> Enum.uniq()
|
||||||
|> Enum.reject(&(&1 == source_language))
|
|> Enum.reject(&(&1 == source_language))
|
||||||
|> Enum.map(fn code ->
|
|> Enum.map(fn code ->
|
||||||
existing_status = Map.get(Map.get(context, :existing_translations, %{}), code)
|
existing_status = Map.get(existing_translations, code)
|
||||||
|
|
||||||
%{
|
%{
|
||||||
code: code,
|
code: code,
|
||||||
name: Map.get(Map.get(context, :language_names, %{}), code, String.upcase(code)),
|
name: Map.get(language_names, code, String.upcase(code)),
|
||||||
flag_emoji: Map.get(Map.get(context, :language_flags, %{}), code, code),
|
flag_emoji: Map.get(language_flags, code, code),
|
||||||
has_existing_translation: not is_nil(existing_status),
|
has_existing_translation: not is_nil(existing_status),
|
||||||
existing_status: existing_status
|
existing_status: existing_status
|
||||||
}
|
}
|
||||||
@@ -255,14 +262,15 @@ defmodule BDS.Desktop.Overlay do
|
|||||||
def set_ai_suggestions_error(overlay, _error_message), do: overlay
|
def set_ai_suggestions_error(overlay, _error_message), do: overlay
|
||||||
|
|
||||||
defp normalize_ai_fields(fields) do
|
defp normalize_ai_fields(fields) do
|
||||||
Enum.map(fields, fn field ->
|
Enum.map(fields, fn %{key: key, label: label, current_value: current,
|
||||||
|
suggested_value: suggested, locked: locked} = field ->
|
||||||
%{
|
%{
|
||||||
key: to_string(Map.get(field, :key, "")),
|
key: to_string(key),
|
||||||
label: Map.get(field, :label, ""),
|
label: label,
|
||||||
current_value: Map.get(field, :current_value, ""),
|
current_value: current,
|
||||||
suggested_value: Map.get(field, :suggested_value, ""),
|
suggested_value: suggested,
|
||||||
accepted: not Map.get(field, :locked, false),
|
accepted: not locked,
|
||||||
locked: Map.get(field, :locked, false),
|
locked: locked,
|
||||||
loading: Map.get(field, :loading, false)
|
loading: Map.get(field, :loading, false)
|
||||||
}
|
}
|
||||||
end)
|
end)
|
||||||
@@ -276,7 +284,7 @@ defmodule BDS.Desktop.Overlay do
|
|||||||
end
|
end
|
||||||
|
|
||||||
defp gallery_images(context) do
|
defp gallery_images(context) do
|
||||||
images = Enum.filter(Map.get(context, :media, []), &Map.get(&1, :is_image, false))
|
images = Enum.filter(Map.get(context, :media, []), & &1.is_image)
|
||||||
post_media_ids = Map.get(context, :post_media_ids, [])
|
post_media_ids = Map.get(context, :post_media_ids, [])
|
||||||
|
|
||||||
case Enum.filter(images, &(&1.id in post_media_ids)) do
|
case Enum.filter(images, &(&1.id in post_media_ids)) do
|
||||||
@@ -289,29 +297,29 @@ defmodule BDS.Desktop.Overlay do
|
|||||||
%{
|
%{
|
||||||
post_id: post.id,
|
post_id: post.id,
|
||||||
title: post.title,
|
title: post.title,
|
||||||
status: to_string(Map.get(post, :status, "draft")),
|
status: post.status,
|
||||||
canonical_url: Map.get(post, :canonical_url, "/posts/#{post.id}"),
|
canonical_url: post.canonical_url,
|
||||||
similarity_score: Map.get(post, :similarity_score)
|
similarity_score: nil
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
defp to_insert_media_result(media) do
|
defp to_insert_media_result(media) do
|
||||||
%{
|
%{
|
||||||
media_id: media.id,
|
media_id: media.id,
|
||||||
title: Map.get(media, :title, ""),
|
title: media.title,
|
||||||
original_name: Map.get(media, :original_name, media.id),
|
original_name: media.original_name,
|
||||||
is_image: Map.get(media, :is_image, false),
|
is_image: media.is_image,
|
||||||
thumbnail_url: Map.get(media, :thumbnail_url)
|
thumbnail_url: media.thumbnail_url
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
defp to_gallery_image(media) do
|
defp to_gallery_image(media) do
|
||||||
%{
|
%{
|
||||||
media_id: media.id,
|
media_id: media.id,
|
||||||
thumbnail_url: Map.get(media, :thumbnail_url),
|
thumbnail_url: media.thumbnail_url,
|
||||||
image_url: Map.get(media, :image_url, Map.get(media, :thumbnail_url)),
|
image_url: media.image_url,
|
||||||
alt_text: Map.get(media, :alt_text),
|
alt_text: media.alt_text,
|
||||||
title: Map.get(media, :title, Map.get(media, :original_name, media.id))
|
title: media.title
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -449,7 +449,7 @@ defmodule BDS.Desktop.ShellCommands do
|
|||||||
end
|
end
|
||||||
|
|
||||||
defp translation_fill_enabled?(metadata) do
|
defp translation_fill_enabled?(metadata) do
|
||||||
([Map.get(metadata, :main_language)] ++ Map.get(metadata, :blog_languages, []))
|
([metadata.main_language] ++ metadata.blog_languages)
|
||||||
|> Enum.map(fn language ->
|
|> Enum.map(fn language ->
|
||||||
language
|
language
|
||||||
|> to_string()
|
|> to_string()
|
||||||
|
|||||||
@@ -266,7 +266,7 @@ defmodule BDS.Desktop.ShellLive.ImportEditor.AnalysisState do
|
|||||||
@spec default_author(term()) :: term()
|
@spec default_author(term()) :: term()
|
||||||
def default_author(project_id) do
|
def default_author(project_id) do
|
||||||
{:ok, metadata} = Metadata.get_project_metadata(project_id)
|
{:ok, metadata} = Metadata.get_project_metadata(project_id)
|
||||||
Map.get(metadata, :default_author)
|
metadata.default_author
|
||||||
end
|
end
|
||||||
|
|
||||||
@spec suggested_definition_name(term()) :: term()
|
@spec suggested_definition_name(term()) :: term()
|
||||||
|
|||||||
@@ -222,7 +222,7 @@ defmodule BDS.Desktop.ShellLive.ImportEditor.TaxonomyEditing do
|
|||||||
{:ok, metadata} = Metadata.get_project_metadata(project_id)
|
{:ok, metadata} = Metadata.get_project_metadata(project_id)
|
||||||
|
|
||||||
%{
|
%{
|
||||||
categories: Enum.uniq(Map.get(metadata, :categories, []) || []),
|
categories: Enum.uniq(metadata.categories || []),
|
||||||
tags: project_id |> Tags.list_tags() |> Enum.map(& &1.name) |> Enum.uniq()
|
tags: project_id |> Tags.list_tags() |> Enum.map(& &1.name) |> Enum.uniq()
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ defmodule BDS.Desktop.ShellLive.SettingsEditor.ManagedCategories do
|
|||||||
|
|
||||||
@spec category_rows(term()) :: term()
|
@spec category_rows(term()) :: term()
|
||||||
def category_rows(metadata) do
|
def category_rows(metadata) do
|
||||||
categories = Map.get(metadata, :categories, [])
|
categories = metadata.categories
|
||||||
settings = Map.get(metadata, :category_settings, %{})
|
settings = metadata.category_settings
|
||||||
|
|
||||||
Enum.map(categories, fn category ->
|
Enum.map(categories, fn category ->
|
||||||
category_settings = Map.get(settings, category, %{})
|
category_settings = Map.get(settings, category, %{})
|
||||||
@@ -167,7 +167,7 @@ defmodule BDS.Desktop.ShellLive.SettingsEditor.ManagedCategories do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp category_names(metadata), do: Map.get(metadata, :categories, [])
|
defp category_names(metadata), do: metadata.categories
|
||||||
|
|
||||||
defp ensure_default_categories(project_id) do
|
defp ensure_default_categories(project_id) do
|
||||||
Enum.reduce_while(Map.keys(@default_category_settings), :ok, fn category, _acc ->
|
Enum.reduce_while(Map.keys(@default_category_settings), :ok, fn category, _acc ->
|
||||||
|
|||||||
@@ -16,17 +16,17 @@ defmodule BDS.Desktop.ShellLive.SettingsEditor.ProjectSettings do
|
|||||||
@spec project_form(term()) :: term()
|
@spec project_form(term()) :: term()
|
||||||
def project_form(metadata) do
|
def project_form(metadata) do
|
||||||
%{
|
%{
|
||||||
"name" => Map.get(metadata, :name, ""),
|
"name" => metadata.name || "",
|
||||||
"description" => Map.get(metadata, :description, ""),
|
"description" => metadata.description || "",
|
||||||
"public_url" => Map.get(metadata, :public_url, ""),
|
"public_url" => metadata.public_url || "",
|
||||||
"main_language" => Map.get(metadata, :main_language) || "en",
|
"main_language" => metadata.main_language || "en",
|
||||||
"default_author" => Map.get(metadata, :default_author, ""),
|
"default_author" => metadata.default_author || "",
|
||||||
"max_posts_per_page" => Integer.to_string(Map.get(metadata, :max_posts_per_page, 50)),
|
"max_posts_per_page" => Integer.to_string(metadata.max_posts_per_page),
|
||||||
"blogmark_category" =>
|
"blogmark_category" =>
|
||||||
Map.get(metadata, :blogmark_category) ||
|
metadata.blogmark_category ||
|
||||||
List.first(Map.get(metadata, :categories, [])) || "article",
|
List.first(metadata.categories) || "article",
|
||||||
"blog_languages" => Map.get(metadata, :blog_languages, []),
|
"blog_languages" => metadata.blog_languages,
|
||||||
"semantic_similarity_enabled" => Map.get(metadata, :semantic_similarity_enabled, false)
|
"semantic_similarity_enabled" => metadata.semantic_similarity_enabled
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ defmodule BDS.Desktop.ShellLive.SettingsEditor.PublishingSettings do
|
|||||||
|
|
||||||
@spec publishing_form(term()) :: term()
|
@spec publishing_form(term()) :: term()
|
||||||
def publishing_form(metadata) do
|
def publishing_form(metadata) do
|
||||||
prefs = Map.get(metadata, :publishing_preferences, %{})
|
prefs = metadata.publishing_preferences
|
||||||
|
|
||||||
%{
|
%{
|
||||||
"ssh_host" => Map.get(prefs, "ssh_host", ""),
|
"ssh_host" => Map.get(prefs, "ssh_host", ""),
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ defmodule BDS.Desktop.ShellLive.SettingsEditor.StyleEditor do
|
|||||||
def current_theme(assigns) do
|
def current_theme(assigns) do
|
||||||
case Metadata.get_project_metadata(assigns.projects.active_project_id) do
|
case Metadata.get_project_metadata(assigns.projects.active_project_id) do
|
||||||
{:ok, metadata} ->
|
{:ok, metadata} ->
|
||||||
case Map.get(metadata, :pico_theme) do
|
case metadata.pico_theme do
|
||||||
nil -> "default"
|
nil -> "default"
|
||||||
"" -> "default"
|
"" -> "default"
|
||||||
theme -> theme
|
theme -> theme
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ defmodule BDS.Generation.Data do
|
|||||||
main = String.downcase(to_string(main_language || ""))
|
main = String.downcase(to_string(main_language || ""))
|
||||||
|
|
||||||
Enum.map(posts, fn post ->
|
Enum.map(posts, fn post ->
|
||||||
post_language = String.downcase(to_string(Map.get(post, :language) || ""))
|
post_language = String.downcase(to_string(post.language || ""))
|
||||||
effective_language = if post_language == "", do: main, else: post_language
|
effective_language = if post_language == "", do: main, else: post_language
|
||||||
|
|
||||||
cond do
|
cond do
|
||||||
@@ -373,18 +373,18 @@ defmodule BDS.Generation.Data do
|
|||||||
excerpt: translation.excerpt,
|
excerpt: translation.excerpt,
|
||||||
content: nil,
|
content: nil,
|
||||||
status: :published,
|
status: :published,
|
||||||
author: Map.get(post, :author),
|
author: post.author,
|
||||||
created_at: post.created_at,
|
created_at: post.created_at,
|
||||||
updated_at: translation.updated_at,
|
updated_at: translation.updated_at,
|
||||||
published_at: translation.published_at || post.published_at,
|
published_at: translation.published_at || post.published_at,
|
||||||
file_path: translation.file_path,
|
file_path: translation.file_path,
|
||||||
tags: Map.get(post, :tags, []),
|
tags: post.tags,
|
||||||
categories: Map.get(post, :categories, []),
|
categories: post.categories,
|
||||||
template_slug: Map.get(post, :template_slug),
|
template_slug: post.template_slug,
|
||||||
language: translation.language,
|
language: translation.language,
|
||||||
do_not_translate: Map.get(post, :do_not_translate, false),
|
do_not_translate: post.do_not_translate,
|
||||||
translation_source_slug: post.slug,
|
translation_source_slug: post.slug,
|
||||||
translation_canonical_language: Map.get(post, :language),
|
translation_canonical_language: post.language,
|
||||||
translation_file_path: translation.file_path
|
translation_file_path: translation.file_path
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ defmodule BDS.Generation.Outputs do
|
|||||||
|
|
||||||
Enum.reject(route_posts, fn post ->
|
Enum.reject(route_posts, fn post ->
|
||||||
is_binary(Map.get(post, :translation_source_slug)) and
|
is_binary(Map.get(post, :translation_source_slug)) and
|
||||||
MapSet.member?(subtree_languages, to_string(Map.get(post, :language)))
|
MapSet.member?(subtree_languages, to_string(post.language))
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -432,11 +432,11 @@ defmodule BDS.Generation.Outputs do
|
|||||||
title: post.title,
|
title: post.title,
|
||||||
content: body,
|
content: body,
|
||||||
slug: post.slug,
|
slug: post.slug,
|
||||||
language: Map.get(post, :language),
|
language: post.language,
|
||||||
excerpt: post.excerpt,
|
excerpt: post.excerpt,
|
||||||
_post_record: post
|
_post_record: post
|
||||||
},
|
},
|
||||||
fn -> render_post_page(post.title, body, post.slug, Map.get(post, :language)) end
|
fn -> render_post_page(post.title, body, post.slug, post.language) end
|
||||||
)}
|
)}
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
@@ -560,11 +560,11 @@ defmodule BDS.Generation.Outputs do
|
|||||||
title: post.title,
|
title: post.title,
|
||||||
content: body,
|
content: body,
|
||||||
slug: post.slug,
|
slug: post.slug,
|
||||||
language: Map.get(post, :language),
|
language: post.language,
|
||||||
excerpt: post.excerpt,
|
excerpt: post.excerpt,
|
||||||
_post_record: post
|
_post_record: post
|
||||||
},
|
},
|
||||||
fn -> render_post_page(post.title, body, post.slug, Map.get(post, :language)) end
|
fn -> render_post_page(post.title, body, post.slug, post.language) end
|
||||||
)}
|
)}
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ defmodule BDS.Generation.Sitemap do
|
|||||||
page_path = Paths.relative_path_to_url_path(Paths.page_output_path(post.slug, nil))
|
page_path = Paths.relative_path_to_url_path(Paths.page_output_path(post.slug, nil))
|
||||||
|
|
||||||
languages =
|
languages =
|
||||||
if Paths.truthy_flag?(Map.get(post, :do_not_translate)),
|
if Paths.truthy_flag?(post.do_not_translate),
|
||||||
do: [plan.language],
|
do: [plan.language],
|
||||||
else: all_languages
|
else: all_languages
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ defmodule BDS.Generation.Validation do
|
|||||||
post_file_path:
|
post_file_path:
|
||||||
source_full_path(
|
source_full_path(
|
||||||
project_data_dir,
|
project_data_dir,
|
||||||
Map.get(post, :translation_file_path) || Map.get(post, :file_path)
|
Map.get(post, :translation_file_path) || post.file_path
|
||||||
),
|
),
|
||||||
generated_updated_at_ms: Map.get(generated_file_updated_at, relative_path, 0)
|
generated_updated_at_ms: Map.get(generated_file_updated_at, relative_path, 0)
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,7 @@ defmodule BDS.Generation.Validation do
|
|||||||
|
|
||||||
%{
|
%{
|
||||||
post_url_path: relative_path_to_url_path(relative_path),
|
post_url_path: relative_path_to_url_path(relative_path),
|
||||||
post_file_path: source_full_path(project_data_dir, Map.get(post, :file_path)),
|
post_file_path: source_full_path(project_data_dir, post.file_path),
|
||||||
generated_updated_at_ms: Map.get(generated_file_updated_at, relative_path, 0)
|
generated_updated_at_ms: Map.get(generated_file_updated_at, relative_path, 0)
|
||||||
}
|
}
|
||||||
end)
|
end)
|
||||||
|
|||||||
@@ -605,6 +605,6 @@ defmodule BDS.ImportExecution do
|
|||||||
|
|
||||||
defp project_default_author(project_id) do
|
defp project_default_author(project_id) do
|
||||||
{:ok, metadata} = Metadata.get_project_metadata(project_id)
|
{:ok, metadata} = Metadata.get_project_metadata(project_id)
|
||||||
Map.get(metadata, :default_author)
|
metadata.default_author
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -252,7 +252,7 @@ defmodule BDS.Posts.AutoTranslation do
|
|||||||
end
|
end
|
||||||
|
|
||||||
defp configured_languages(metadata) do
|
defp configured_languages(metadata) do
|
||||||
([Map.get(metadata, :main_language)] ++ Map.get(metadata, :blog_languages, []))
|
([metadata.main_language] ++ metadata.blog_languages)
|
||||||
|> Enum.map(&normalize_language/1)
|
|> Enum.map(&normalize_language/1)
|
||||||
|> Enum.reject(&(&1 in [nil, ""]))
|
|> Enum.reject(&(&1 in [nil, ""]))
|
||||||
|> Enum.uniq()
|
|> Enum.uniq()
|
||||||
|
|||||||
@@ -312,7 +312,7 @@ defmodule BDS.Posts.TranslationValidation do
|
|||||||
|
|
||||||
defp legacy_missing_entries(source_posts, translation_rows, metadata) do
|
defp legacy_missing_entries(source_posts, translation_rows, metadata) do
|
||||||
configured_languages =
|
configured_languages =
|
||||||
([Map.get(metadata, :main_language)] ++ Map.get(metadata, :blog_languages, []))
|
([metadata.main_language] ++ metadata.blog_languages)
|
||||||
|> Enum.map(&do_normalize_language/1)
|
|> Enum.map(&do_normalize_language/1)
|
||||||
|> Enum.reject(&(&1 in [nil, ""]))
|
|> Enum.reject(&(&1 in [nil, ""]))
|
||||||
|> Enum.uniq()
|
|> Enum.uniq()
|
||||||
@@ -444,7 +444,7 @@ defmodule BDS.Posts.TranslationValidation do
|
|||||||
language = do_normalize_language(source_post.language)
|
language = do_normalize_language(source_post.language)
|
||||||
|
|
||||||
if language == "" do
|
if language == "" do
|
||||||
do_normalize_language(Map.get(metadata, :main_language))
|
do_normalize_language(metadata.main_language)
|
||||||
else
|
else
|
||||||
language
|
language
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ defmodule BDS.Preview do
|
|||||||
with :ok <- ensure_running(state.current, project_id),
|
with :ok <- ensure_running(state.current, project_id),
|
||||||
{:ok, payload} <- load_draft_preview_payload(project_id, post_id, query_params) do
|
{:ok, payload} <- load_draft_preview_payload(project_id, post_id, query_params) do
|
||||||
body =
|
body =
|
||||||
case Rendering.render_post_page(project_id, Map.get(payload, :template_slug), payload) do
|
case Rendering.render_post_page(project_id, payload.template_slug, payload) do
|
||||||
{:ok, rendered} -> rendered
|
{:ok, rendered} -> rendered
|
||||||
{:error, _reason} -> render_draft(payload)
|
{:error, _reason} -> render_draft(payload)
|
||||||
end
|
end
|
||||||
@@ -178,7 +178,7 @@ defmodule BDS.Preview do
|
|||||||
defp resolve_draft_request(project_id, post_id, query_params) do
|
defp resolve_draft_request(project_id, post_id, query_params) do
|
||||||
with {:ok, payload} <- load_draft_preview_payload(project_id, post_id, query_params) do
|
with {:ok, payload} <- load_draft_preview_payload(project_id, post_id, query_params) do
|
||||||
body =
|
body =
|
||||||
case Rendering.render_post_page(project_id, Map.get(payload, :template_slug), payload) do
|
case Rendering.render_post_page(project_id, payload.template_slug, payload) do
|
||||||
{:ok, rendered} -> rendered
|
{:ok, rendered} -> rendered
|
||||||
{:error, _reason} -> render_draft(payload)
|
{:error, _reason} -> render_draft(payload)
|
||||||
end
|
end
|
||||||
|
|||||||
98
test/bds/csm032_map_get_pattern_match_test.exs
Normal file
98
test/bds/csm032_map_get_pattern_match_test.exs
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
defmodule BDS.CSM032MapGetPatternMatchTest do
|
||||||
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
|
@metadata_consumers [
|
||||||
|
"lib/bds/posts/translation_validation.ex",
|
||||||
|
"lib/bds/posts/auto_translation.ex",
|
||||||
|
"lib/bds/desktop/shell_commands.ex",
|
||||||
|
"lib/bds/desktop/shell_live/settings_editor/project_settings.ex",
|
||||||
|
"lib/bds/desktop/shell_live/settings_editor/style_editor.ex",
|
||||||
|
"lib/bds/desktop/shell_live/settings_editor/managed_categories.ex",
|
||||||
|
"lib/bds/desktop/shell_live/settings_editor/publishing_settings.ex",
|
||||||
|
"lib/bds/desktop/shell_live/import_editor/taxonomy_editing.ex",
|
||||||
|
"lib/bds/desktop/shell_live/import_editor/analysis_state.ex",
|
||||||
|
"lib/bds/import_execution.ex"
|
||||||
|
]
|
||||||
|
|
||||||
|
@metadata_atom_keys ~w(main_language blog_languages categories category_settings
|
||||||
|
publishing_preferences name description public_url default_author
|
||||||
|
max_posts_per_page blogmark_category pico_theme
|
||||||
|
semantic_similarity_enabled)
|
||||||
|
|
||||||
|
describe "source-level: no Map.get(metadata, :atom_key) on metadata struct" do
|
||||||
|
for file <- @metadata_consumers do
|
||||||
|
test "#{Path.basename(file)} uses dot access instead of Map.get for metadata atom keys" do
|
||||||
|
source = File.read!(unquote(file))
|
||||||
|
|
||||||
|
for key <- @metadata_atom_keys do
|
||||||
|
refute source =~ "Map.get(metadata, :#{key}",
|
||||||
|
"#{unquote(file)} should use metadata.#{key} instead of Map.get(metadata, :#{key})"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "source-level: overlay.ex uses pattern matching for known structures" do
|
||||||
|
test "delete_details uses pattern matching instead of Map.get" do
|
||||||
|
source = File.read!("lib/bds/desktop/overlay.ex")
|
||||||
|
refute source =~ "Map.get(delete_details,",
|
||||||
|
"overlay.ex should pattern match delete_details instead of using Map.get"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "merge_details uses pattern matching instead of Map.get" do
|
||||||
|
source = File.read!("lib/bds/desktop/overlay.ex")
|
||||||
|
refute source =~ "Map.get(merge,",
|
||||||
|
"overlay.ex should pattern match merge_details instead of using Map.get"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "media struct fields use dot access in to_insert_media_result" do
|
||||||
|
source = File.read!("lib/bds/desktop/overlay.ex")
|
||||||
|
|
||||||
|
refute source =~ ~r/to_insert_media_result.*Map\.get\(media/s &&
|
||||||
|
source =~ "defp to_insert_media_result",
|
||||||
|
"to_insert_media_result should use dot access for media fields"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "media struct fields use dot access in to_gallery_image" do
|
||||||
|
source = File.read!("lib/bds/desktop/overlay.ex")
|
||||||
|
|
||||||
|
refute source =~ ~r/to_gallery_image.*Map\.get\(media/s &&
|
||||||
|
source =~ "defp to_gallery_image",
|
||||||
|
"to_gallery_image should use dot access for media fields"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "source-level: generation pipeline uses dot access for Post struct fields" do
|
||||||
|
test "outputs.ex uses post.language instead of Map.get(post, :language)" do
|
||||||
|
source = File.read!("lib/bds/generation/outputs.ex")
|
||||||
|
refute source =~ "Map.get(post, :language)",
|
||||||
|
"outputs.ex should use post.language"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "data.ex uses dot access for Post struct fields in build_published_translation_variant" do
|
||||||
|
source = File.read!("lib/bds/generation/data.ex")
|
||||||
|
refute source =~ "Map.get(post, :author)",
|
||||||
|
"data.ex should use post.author"
|
||||||
|
refute source =~ "Map.get(post, :tags",
|
||||||
|
"data.ex should use post.tags"
|
||||||
|
refute source =~ "Map.get(post, :categories",
|
||||||
|
"data.ex should use post.categories"
|
||||||
|
refute source =~ "Map.get(post, :template_slug)",
|
||||||
|
"data.ex should use post.template_slug"
|
||||||
|
refute source =~ "Map.get(post, :do_not_translate",
|
||||||
|
"data.ex should use post.do_not_translate"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "validation.ex uses post.file_path instead of Map.get(post, :file_path)" do
|
||||||
|
source = File.read!("lib/bds/generation/validation.ex")
|
||||||
|
refute source =~ "Map.get(post, :file_path)",
|
||||||
|
"validation.ex should use post.file_path"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "sitemap.ex uses post.do_not_translate instead of Map.get" do
|
||||||
|
source = File.read!("lib/bds/generation/sitemap.ex")
|
||||||
|
refute source =~ "Map.get(post, :do_not_translate)",
|
||||||
|
"sitemap.ex should use post.do_not_translate"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -206,11 +206,17 @@ defmodule BDS.Desktop.OverlayTest do
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
delete_details: %{
|
delete_details: %{
|
||||||
|
title: "Delete Media",
|
||||||
entity_name: "Street Scene",
|
entity_name: "Street Scene",
|
||||||
entity_type: "media",
|
entity_type: "media",
|
||||||
reference_list: ["Photo Walk", "Trip Notes"]
|
reference_list: ["Photo Walk", "Trip Notes"]
|
||||||
},
|
},
|
||||||
merge_details: %{target: "travel", count: 3}
|
merge_details: %{
|
||||||
|
target: "travel",
|
||||||
|
count: 3,
|
||||||
|
title: "Merge 3 tags into travel?",
|
||||||
|
message: "Cannot be undone."
|
||||||
|
}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user