1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Publishで記事にツイートボタンを表示する方法(Swift)

Last updated at Posted at 2022-04-05

「PublishでWebサイトを構築する」は6部構成です。
記事を順番に読み進めると、PublishでWebサイトが構築できるようになります。

第1部: セットアップ&使い方
第2部: カスタムテーマの作成
第3部: プラグインのインストール
第4部: プラグインの作成(未投稿)
第5部: ツイートボタンの表示 ←イマココ
第6部: はてなブックマークボタンの表示

はじめに

Publishで記事にツイートボタンを表示する方法を紹介します。

環境

  • OS:macOS Monterey 12.2.1
  • Xcode:13.3 (13E113)
  • Swift:5.6
  • Publish:0.8.0

ツイートボタンのHTMLの把握

まずツイートボタンのHTMLを把握し、生成後のイメージを掴みます。
詳細は以下の記事をご参照ください。

実装

URLエンコード処理の実装

String 型をURLエンコードする処理を実装します。
私は以下の記事の内容をほぼそのまま使わせていただきました。

String+URL.swift
import Foundation

extension String {
    func urlEncoded() -> String {
        let allowedChars = CharacterSet.alphanumerics.union(.init(charactersIn: "/?-._~"))
        let decoded = removingPercentEncoding ?? self
        return decoded.addingPercentEncoding(withAllowedCharacters: allowedChars) ?? decoded
    }
}

"{文字列}".urlEncoded() で文字列をURLエンコードできるようになりました。

"iOS Osushi🍣".urlEncoded() // "iOS%20Osushi%F0%9F%8D%A3"

クエリストリングに渡す文字列はすべてURLエンコードすべきです。

HTML構築処理の更新

テーマのHTML構築処理を更新し、ツイートボタンを配置します。

Theme+IosOsushi.swift
private struct IosOsushiHTMLFactory<Site: Website>: HTMLFactory {
    func makeItemHTML(for item: Item<Site>, context: PublishingContext<Site>) throws -> HTML {
        HTML(
            .lang(context.site.language),
            .head(for: item, on: context.site),
            .body(
+               .script(.async(), .src("https://platform.twitter.com/widgets.js")),
                .class("item-page"),
                .components {
                    SiteHeader(context: context, selectedSelectionID: item.sectionID)
                    Wrapper {
                        Article {
+                           Div {
+                               TweetButton(item: item, site: context.site)
+                           }
+                           .class("share-buttons")
                            Div(item.content.body).class("content")
                            Span("Tagged with: ")
                            ItemTagList(item: item, site: context.site)
                        }
                    }
                    SiteFooter()
                }
            )
        )
    }

+   private struct TweetButton<Site: Website>: Component {
+       private var tweetText: String { "\(item.title) | \(site.name)" }
+       private var urlString: String { site.url.absoluteString + item.path.absoluteString }
+       private let hashtag = "ios_osushi"
+       private let username = "ios_osushi"
+
+       var item: Item<Site>
+       var site: Site
+       var body: Component {
+           Link("ツイート", url: "https://twitter.com/intent/tweet?text=\(tweetText.urlEncoded())&url=\(urlString.urlEncoded())&hashtags=\(hashtag.urlEncoded())&via=\(username.urlEncoded())")
+               .class("twitter-share-button")
+       }
+   }
}

ボタンの下にマージンを付けます。
CSSに詳しくないので、 class の命名や、そもそも class にマージンを付けるのがいいのかなどがわかりません。
他にいい方法があれば教えていただけると嬉しいです。

styles.css
+ .share-buttons {
+     margin-bottom: 10px;
+ }

JSの読み込みは .body() 以外の箇所に仕込む方法がわからなかったため、 <body>...</body> で行っています。

今回の TweetButton のように、要素のまとまりは Component を継承した構造体で表現すると可読性が向上します。
body に要素のまとまりを記述します。

ツイートのテキストやURL、ハッシュタグ、ユーザー名は、必要に応じて変更してください。

publish-cli run を実行し、記事の上部にツイートボタンが表示されたらOKです。
スクリーンショット 2022-04-06 11.13.30.png

おわりに

これで記事にツイートボタンを表示できました!

参考リンク

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?