{
  "sha": "5a583102f2088b4a54058c87a97d7aeea4b9a410",
  "message": "在搜尋欄右側新增 SKYTICAL 官方 FB 與 IG (#375)",
  "author": {
    "login": "nnneeeooo-nnneeeooo",
    "name": "CHI HSUN YANG",
    "email": "125815713+nnneeeooo-nnneeeooo@users.noreply.github.com"
  },
  "committer": {
    "login": "web-flow",
    "name": "GitHub",
    "email": "noreply@github.com"
  },
  "created_at": "2026-10-23T18:43:53Z",
  "files": [
    {
      "filename": "static/site.css",
      "previous_filename": "",
      "status": "modified",
      "additions": 24,
      "deletions": 2,
      "changes": 26
    },
    {
      "filename": "templates/base.html",
      "previous_filename": "",
      "status": "modified",
      "additions": 18,
      "deletions": 0,
      "changes": 18
    },
    {
      "filename": "tests/test_search.py",
      "previous_filename": "",
      "status": "modified",
      "additions": 16,
      "deletions": 1,
      "changes": 17
    }
  ],
  "diff": "@@ -78,11 +78,13 @@ a.ticker-item:hover .ticker-time { color: var(--color-accent); }\\n }\\n /* — Google-style search, deliberately the first row of every page — */\\n .header-search-row {\\n+  display: flex; align-items: center; justify-content: center; gap: 16px;\\n   padding: 11px 20px; border-bottom: 1px solid var(--color-divider);\\n   background: var(--color-bg);\\n }\\n .header-search-form {\\n-  width: min(720px, 100%); min-height: 48px; margin: 0 auto;\\n+  width: min(720px, 100%); max-width: 720px; min-width: 0;\\n+  flex: 1; min-height: 48px; margin: 0;\\n   display: grid; grid-template-columns: 22px minmax(0, 1fr) auto 40px;\\n   align-items: center; gap: 9px; padding: 3px 5px 3px 16px;\\n   border: 1px solid color-mix(in srgb, var(--color-text) 24%, transparent);\\n@@ -123,6 +125,16 @@ a.ticker-item:hover .ticker-time { color: var(--color-accent); }\\n .header-search-clear:focus-visible, .header-search-submit:focus-visible {\\n   outline: 2px solid var(--color-accent); outline-offset: 2px;\\n }\\n+.header-social-links { display: flex; flex: 0 0 auto; align-items: center; gap: 8px; }\\n+.header-social-links a {\\n+  display: inline-flex; align-items: center; justify-content: center;\\n+  width: 44px; height: 44px; border-radius: 50%;\\n+  border: 1px solid color-mix(in srgb, var(--color-text) 24%, transparent);\\n+  color: var(--color-text); text-decoration: none; touch-action: manipulation;\\n+}\\n+.header-social-links svg { display: block; width: 22px; height: 22px; }\\n+.header-social-links a:hover { color: var(--color-accent); border-color: currentColor; }\\n+.header-social-links a:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 3px; }\\n \\n .utility-bar { border-bottom: 1px solid var(--color-divider); }\\n .utility-row {\\n@@ -883,8 +895,18 @@ html[lang=\"en\"] .search-help-term:not(:last-child) { margin-right: .3em; }\\n   .marquee-track .ticker-pass:nth-child(2) { display: none; }\\n }\\n \\n+@media (max-width: 400px) {\\n+  .header-search-row .header-search-form {\\n+    grid-template-columns: minmax(0, 1fr) auto 36px;\\n+    gap: 5px;\\n+  }\\n+  .header-search-form > .header-search-icon { display: none; }\\n+  .header-search-form .header-search-clear { width: 24px; }\\n+}\\n+\\n @media (max-width: 640px) {\\n-  .header-search-row { padding: 9px 12px; }\\n+  .header-search-row { padding: 9px 12px; gap: 8px; }\\n+  .header-social-links { gap: 4px; }\\n   .header-search-form {\\n     min-height: 44px; grid-template-columns: 20px minmax(0, 1fr) auto 36px;\\n     gap: 7px; padding-left: 13px;\\n@@ -87,6 +87,24 @@\\n         </svg>\\n       </button>\\n     </form>\\n+    <nav class=\"header-social-links\" aria-label=\"{% if lang == 'zh' %}SKYTICAL官方社群{% else %}SKYTICAL social media{% endif %}\">\\n+      <a href=\"https://www.facebook.com/profile.php?id=61595860824748\"\\n+         target=\"_blank\" rel=\"noopener noreferrer\" title=\"SKYTICAL Facebook\"\\n+         aria-label=\"SKYTICAL Facebook{% if lang == 'zh' %}（另開分頁）{% else %} (opens in a new tab){% endif %}\">\\n+        <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\" focusable=\"false\">\\n+          <path d=\"M13 22v-8h3l.6-4H13V7.5c0-1.1.5-1.5 1.6-1.5H17V2.3c-.8-.2-2-.3-3.2-.3C10.5 2 8.5 4 8.5 7.5V10H6v4h2.5v8Z\"></path>\\n+        </svg>\\n+      </a>\\n+      <a href=\"https://www.instagram.com/skyticalnews/\"\\n+         target=\"_blank\" rel=\"noopener noreferrer\" title=\"SKYTICAL Instagram\"\\n+         aria-label=\"SKYTICAL Instagram{% if lang == 'zh' %}（另開分頁）{% else %} (opens in a new tab){% endif %}\">\\n+        <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\" aria-hidden=\"true\" focusable=\"false\">\\n+          <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"5\"></rect>\\n+          <circle cx=\"12\" cy=\"12\" r=\"4\"></circle>\\n+          <circle cx=\"17.5\" cy=\"6.5\" r=\"1\" fill=\"currentColor\" stroke=\"none\"></circle>\\n+        </svg>\\n+      </a>\\n+    </nav>\\n   </div>\\n   <div class=\"utility-bar\">\\n     <div class=\"utility-row\">\\n@@ -8,6 +8,8 @@\\n import unicodedata\\n from pathlib import Path\\n \\n+from bs4 import BeautifulSoup\\n+\\n ROOT = Path(__file__).resolve().parent.parent\\n sys.path.insert(0, str(ROOT / \"pipeline\"))\\n \\n@@ -239,6 +241,20 @@ def main() -> None:\\n     assert re.search(r'/assets/search\\.js\\?v=[0-9a-f]{10}', zh)\\n     assert home.index('class=\"header-search-row\"') < home.index('id=\"clock-utc\"')\\n     assert home.index('class=\"header-search-row\"') < home.index('class=\"brand-row\"')\\n+    for page in (home, article, en):\\n+        social = BeautifulSoup(page, \"html.parser\").select_one(\\n+            \".header-search-row .header-social-links\")\\n+        assert social is not None and social.find_parent(\"form\") is None\\n+        links = social.select(\"a\")\\n+        assert [link[\"href\"] for link in links] == [\\n+            \"https://www.facebook.com/profile.php?id=61595860824748\",\\n+            \"https://www.instagram.com/skyticalnews/\",\\n+        ]\\n+        for link in links:\\n+            assert link[\"target\"] == \"_blank\"\\n+            assert {\"noopener\", \"noreferrer\"} <= set(link[\"rel\"])\\n+            assert \"SKYTICAL\" in link[\"aria-label\"]\\n+            assert link.select_one('svg[aria-hidden=\"true\"]') is not None\\n     main_markup = re.search(r'<main class=\"search-page\">(.*?)</main>', zh,\\n                             re.DOTALL).group(1)\\n     assert \"<form\" not in main_markup\\n@@ -251,7 +267,6 @@ def main() -> None:\\n     assert \".header-search-submit\" in css\\n     assert \"航空公司 IATA／ICAO 代碼\" in zh\\n     assert \"airline IATA/ICAO codes\" in en\\n-    from bs4 import BeautifulSoup\\n     for markup, language in ((zh, \"zh\"), (en, \"en\")):\\n         header = BeautifulSoup(markup, \"html.parser\").select_one(\".search-header\")\\n         groups = header.select(\".search-help-group\")"
}
