import: drop trailing semicolons from a Monica company
Monica kept a vCard's raw ORG as company text, the trailing semicolon too;
escaped as text it joined the name, so the composer trims it before it's through.
A company that was only a semicolon now writes no ORG line at all,
the same blank Monica's own migration made of it, nulling ";" for good and all.

Assisted-by: Claude Opus 5.5 via Claude Code
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
change xopslkqnsuulwzmtqmvyvsqpytrwnwsv
commit a79b68719f6d1c854d1953b6f597fc816b78670b
author Alpha Chen <alpha@kejadlen.dev>
date
parent mtsrkryz
diff --git a/lib/pro_tacts/import/monica.rb b/lib/pro_tacts/import/monica.rb
index c8955c4..9ee66b6 100644
--- a/lib/pro_tacts/import/monica.rb
+++ b/lib/pro_tacts/import/monica.rb
@@ -154,7 +154,12 @@ module ProTacts
         lines << "N:#{last};#{first};#{middle};;"
         lines << "FN:#{VCard.escape(name_of(properties))}"
         lines << text("NICKNAME", properties["nickname"])
-        lines << text("ORG", properties["company"])
+        # Monica's company is free text, and one that came in by vCard
+        # kept ORG's raw value, the trailing semicolon macOS writes
+        # included — Monica's own migration nulls a company of ";"
+        # alone (2021_10_14_212144_v_card_company). Escaped as text,
+        # that semicolon would be part of the name.
+        lines << text("ORG", properties["company"].to_s.sub(/[;\s]+\z/, ""))
         lines << text("TITLE", properties["job"])
         lines << birthday(properties["birthdate"])
 
diff --git a/test/pro_tacts/import/test_monica.rb b/test/pro_tacts/import/test_monica.rb
index f9e64cd..475f199 100644
--- a/test/pro_tacts/import/test_monica.rb
+++ b/test/pro_tacts/import/test_monica.rb
@@ -129,6 +129,15 @@ class ImportMonicaTest < Minitest::Test
     assert_equal PIXEL, card.property("PHOTO").value
   end
 
+  # A company Monica kept as a vCard's raw ORG loses the trailing
+  # semicolons, which escaped as text would be part of its name; one
+  # that was nothing else is no company.
+  def test_a_companys_trailing_semicolons_are_dropped
+    assert_equal "Acme", card_for(export(jane("company" => "Acme; ")), "Jane Booles").property("ORG").value
+    assert_equal "Acme", card_for(export(jane("company" => "Acme;;")), "Jane Booles").property("ORG").text
+    assert_nil card_for(export(jane("company" => ";")), "Jane Booles").property("ORG")
+  end
+
   # One NOTE, the invariant a contact keeps
   # (docs/plans/2026-09-25-one-note-per-contact.md): the prose first,
   # then what Monica keeps as records, spelled out.