Hello.

I am Paul Kinlan.

A Developer Advocate for Chrome and the Open Web at Google.

I love the web. The web should allow anyone to access any experience that they need without the need for native install or content walled garden.

Using Web Mentions in a static site (Hugo)

Paul Kinlan

私のブログは完全に静的なサイトで、Hugoで構築され、Zeitでホストされています。これは私にとって素晴らしいソリューションです。シンプルなブログは非常にシンプルな展開プロセスを持ち、非常に高速にロードされます。 静的に生成されたサイトにはいくつかの欠点がありますが、最大のものは、動的なものをページに統合する必要がある場合です(コメントなど)。動的コンテンツを簡単にホストできないということは、最終的にはサードパーティのJavaScriptに依存してページにフルアクセスできるようになり、何をしているのかわからなくなることを意味します。ユーザーを追跡したり、ページを遅くしたりする可能性があります負荷。 私は最近、ユーザーがコメントにスクロールするときに( IntersectionObserverを使用して)ロードするだけで、現在のコメントウィジェット(Disqus)をクリティカルレンダーパスから削除しました。すべて一緒に。 Webmention仕様を入力します。 Webmentionは、別のサイトがサイト上のコンテンツに「メンション」を付けた(または「いいね!」)ときに、サイト作成者に連絡する方法を説明する仕様です。これにより、最終的にはサイトにリンクするコンテンツを発見するための分散化された方法が可能になり、できれば価値と洞察が得られます。 Webmention仕様では、「メンションサイト」が言ったことを伝えるために使用するデータ形式については説明していません。標準のマイクロフォーマットまたはページのコンテンツを理解する他のメカニズムを使用して解析する必要があります。これは素晴らしいことですが、 webmention.ioなどの集中型サービスにつながり、ページから意味を引き出すために非常に必要なインフラストラクチャを提供すると考えています。 私はWebmentionを使用するというアイデアが好きでしたが、誰かがあなたのサイトに言及したときの通知を取得(そしておそらく保存)するためにサーバー側のセットアップが必要です。これは私のサイトにあるような静的ビルダーでは常に可能ではありません。この投稿の残りの部分では、ZeitがホストするHugoビルドでホストされているいいね!、言及、再投稿の方法について簡単に説明します。 ステップ1-Webmentionハブを見つける webmention.ioを見つけました。着信するpingbackとメンションを処理します。また、呼び出し元のサイトが実際にコンテンツにリンクしていることを検証し、最終的にコンテキストを理解できるようにページからデータを解析します。 Webmention.ioは、オープン認証プロセスを介してサイトを所有していることを検証します(認証プロバイダーを指すrel = meを探すのはきれいでした) ステップ###を処理できることをページに伝えます これは、次の2つのlinkタグを追加するのと同じくらい簡単です <link rel="webmention" href="https://webmention.io/paul.kinlan.me/webmention"> <link rel="pingback" href="https://webmention.io/paul.kinlan.me/xmlrpc"> ステップ3-webmention.io APIをサイトに統合します ここには2つのオプションがあります。webmention.ioAPIを呼び出すウィジェットをページに追加するか、webmention.io APIをビルドステップに統合できます。 JSをホストするサードパーティはできるだけ少なくしたいので、後者を選択しました。デプロイメントプロセスにWebmentionを統合しました。 ビルドが高速であるため、Hugoを使用します。これを念頭に置いて、Webmention APIを最適な方法でHugoに統合する方法を検討する必要がありました。厳しい制約は、サイトのすべてのページでAPIエンドポイントを呼び出さないことでした。私には多くのページがあり、まだ多くのコメントはありません。 幸いなことに、Webmention.ioサイトは、ドメインに関するすべての言及を受け取ることができる便利なエンドポイントを提供します。不幸なことに、このファイルには、サイトに対して行われたすべてのアクションに対して1つのエントリが含まれています。 Hugoには、特定のページのテンプレートに直接プルできるデータファイルの概念もあるため、Webmentionデータファイルを、Hugoテンプレート内で読みやすい新しい構造にマッピングする必要があります。 私が選択したプロセスは以下のとおりですが、要約は、アクションのリストから、APIによって公開されたアクション(再投稿や返信など)を含むURLの辞書に配列を変換し、最後のステップがURLの辞書を、URLのmd5ハッシュという名前の個々のファイルに分割します。 "use strict"; const fs = require('fs'); const fetch = require('node-fetch'); const md5 = require('md5'); const processMentionsJson = (data) => { const urlData = {}; data.children.forEach(item => { const wmProperty = item["wm-property"]; const url = item[wmProperty]; if(url in urlData === false) urlData[url] = {}; const urlDataItem = urlData[url]; if(wmProperty in urlDataItem === false) urlDataItem[wmProperty] = []; urlDataItem[wmProperty].

Read More

Webmention.app

Paul Kinlan

私はWebmentionsのアイデアが大好きですが、それを自分のサイトに実装する時間がありませんでした。高レベルのWeb言及では、Web上の他のコンテンツにコメント、いいね、返信したり、Disqus(私のサイトから削除したい)などのツールで一元化することなく、そのコンテンツに表示することができます。 Webメンションは、送信者と受信者の2つのコンポーネントに分割されます。受信者は、私が投稿を書いているサイトであり、彼らのサイトには、インバウンドリンクやブログへの反応を示す何かがあるかもしれません。そして、送信者は私です。私が作成したリモートサイトに、作成したコンテンツに反応させる必要があります。 かなり素晴らしいRemy Sharpがwebmention.appを作成して、問題の一部を解決しましたwebmention.app送信です。 Remyのツールを使用すると、CLIスクリプトを呼び出すだけで、リンクした潜在的な受信者に「ping」を簡単に送信できます。 私は、Hugoと静的ビルダーツールを使用してZeitを使用してブログをホストしているため、 relatively trivial for me to add in support for webmention app 。 npm i webmentionだけをnpm i webmentionしてから、 build.shファイルからCLIバージョンのツールをbuild.shます。これは本当に簡単です。 投稿を作成すると、サイトに関するコンテンツを作成したすべての新しいURLに簡単なpingが送信されます。

Read More

Creating a commit with multiple files to Github with JS on the web

Paul Kinlan

私のサイトはentirely staticです。 Hugoで構築され、 HugoでホストされていZeit 。私はセットアップにかなり満足しています。インスタントビルドと超高速CDNによるコンテンツ配信に近づき、状態を管理する必要がないため、必要なすべてのことを実行できます。 このサイトのpodcast creatorと、静的にホストされたサイトに新しいコンテンツをすばやく投稿できるsimple UIを作成しました。 そう。どうやってやったの? これは、私のGithub Repoに対するFirebase Auth、コンテンツを編集するEditorJS(それはきちんとしている)、およびリポジトリにコミットするOctokat.jsと、Hugoビルドを行うZeitのGithub統合の組み合わせです。この設定により、ユーザーがWordpressのようなCMSを使用したデータベースに投稿を作成する方法と同様に、完全に自己ホスト型の静的CMSを作成できます。 この投稿では、インフラストラクチャの一部に焦点を当てるだけです。Githubに複数のファイルをコミットするのは、少し時間がかかったためです。 コード全体は、私のrepoで見ることができます。 Githubに直接コミットする必要があるWeb UIを構築している場合、私が見つけた最高のライブラリはOctokatです-CORSで動作し、Github APIのAPI面全体を処理するようです。 Gitは、ツリー、ブランチ、その他の部分がどのように機能するかを理解することになると、複雑な獣になる可能性があるので、それを簡単にする決定をしました。 heads/masterとして知られるmasterブランチにのみプッシュできます。 1.特定のファイルが保存される場所がわかります(Hugoは特定のディレクトリ構造を強制します) それを念頭に置いて、複数のファイルでコミットを作成する一般的なプロセスは次のとおりです。 リポジトリへの参照を取得します。 heads/masterブランチのツリーの先端への参照を取得します。 1.コミットするファイルごとにblobを作成し、 sha識別子、パス、モードへの参照を配列に保存します。 1.すべてのブロブを含む新しいtreeを作成して、 heads/masterツリーの先端への参照に追加し、このツリーへの新しいshaポインターをshaます。 1.この新しいツリーを指すコミットを作成し、 heads/masterブランチにプッシュします。 コードはほとんどそのフローに従います。特定の入力のパス構造を想定できるため、複雑なUIやファイルの管理を構築する必要はありません。 const createCommit = async (repositoryUrl, filename, data, images, commitMessage, recording) => { try { const token = localStorage.getItem('accessToken'); const github = new Octokat({ 'token': token }); const [user, repoName] = repositoryUrl.split('/'); if(user === null || repoName === null) { alert('Please specifiy a repo'); return; } const markdownPath = `site/content/${filename}.

Read More

Translating a blog using Google Cloud Translate and Hugo

Paul Kinlan

私は最近、Google4Indiaイベント(近いうちに報告)に出席し、多くの企業や開発者と出会うためにインドへの旅行から帰ってきました。議論された最も興味深い変更の1つは、国のユーザーの言語でより多くのコンテンツを求めていたことでした。特に、ユーザーの言語で検索しやすくすること、コンテンツを見つけること、テキストまたは音声形式でユーザにそれを読み戻すことができます。 旅行全体が私に考えさせてくれました。私のブログはHugoで構築されています。 Hugoは現在、複数の言語で書かれたコンテンツをサポートしています。 Hugoは完全に静的なので、新しいコンテンツを作成することは、新しいファイルを作成してビルドシステムに魔法をかけることの問題です。翻訳ツールを使用して静的コンテンツを実行することで、より多くの人がコンテンツを利用できるようにすることができます。なぜなら、コンテンツの翻訳者は非常に高額なためです。 私の飛行前にイギリスに帰国する数時間前に、自分のマークダウンファイルを取得し、Google Cloud Translateで実行してクイック検索を作成するスクリプトを作成しました私はすぐにホストすることができますページの翻訳。ソリューション全体を以下に示します。これは比較的基本的なプロセッサーで、「コード」を無視したHugoプリアンブルを無視し、プル・クォートを無視しています。これらは常に書かれたままにしておくことを前提としていました。 注:翻訳用のラーニングソフトウェアのように見えるので、学習ツールでGoogle Translatedコンテンツをアルゴリズムの入力として使用しないようにページをマークアップすることが重要です(https://cloud.google.com/translate/マークアップ)。 // Imports the Google Cloud client library const Translate = require('@google-cloud/translate'); const program = require('commander'); const fs = require('fs'); const path = require('path'); program .version('0.1.0') .option('-s, --source [path]', 'Add in the source file.') .option('-t, --target [lang]', 'Add target language.') .parse(process.argv); // Creates a client const translate = new Translate({ projectId: 'html5rocks-hrd' }); const options = { to: program.target, }; async function translateLines(text) { if(text === ' ') return ' '; const output = []; let results = await translate.

Read More

Configuring hugo server to serve 'mjs' ES modules

Paul Kinlan

デフォルトでは、Hugoは正しいコンテンツタイプの.mjsファイルを提供しません。実際、最近までhugoはMIMEタイプごとに複数のファイル拡張子を提供することはできませんでした。これは修正されたv0.43のように見えます。 [mediaTypes] [mediaTypes."text/javascript"] suffixes = ["js", "mjs"] 全文を読む。 上記のコードでは、正しいMIMEタイプのESモジュール用のmjsファイルを提供できます(メモモジュールは 'text / javascript'で提供する必要があります)。これはローカルテストにのみ必要です。ホスティングは別の問題です:)

Read More