長々とこだわっている「自サイトブログカードのリンクターゲット」の件、そろそろ実装できるものに仕上げないといけません(笑)。
これまでこんなことをやってきました。
01hatenablog-parts.com/embed を 自サイト/embed に
前回は、XMLHttpRequest を使ってターゲットファイルを読み込み、そこからOGPデータを取り出してブログカードを作りましたが、ふと、自サイト名/embed でもブログカードはできることを思い出し、であれば、同じく XMLHttpRequest で 自サイト/embed/エントリー
にアクセスすればブログカードそのもののファイルが取れるのではないかと思いつきました。
そうすれば、記事作成時に特別にマークアップする必要もなく、通常の iframe のままにしておき、それを div に置き換えることもできそうです。
で、やってみたのが次のスクリプトです。
02XMLHttpRequest を使い embed-wrapper を取り出す
「非同期処理を Promise と then で書き直す」をご覧ください。
(function(){ var article = document.getElementsByTagName('article')[0]; if(article !== undefined){ var iframes = article.getElementsByTagName('iframe'); var reg = new RegExp('http(s)?%3A%2F%2F' + location.hostname + '.+
- ブログカードは記事内にしかありえませんから article タグに限定し、
- 複数あるかも知れない iframe を取り出し、
- ひとつひとつの iframe の src が自サイトであるかをチェックし、
- URL の entry を embed に差し替えて HTML ファイルを読み込み、
- DOM パースして
<div class="embed-wrapper"></div>
だけ取り出し、- リンクターゲットを
_top
に差し替え、- iframe と div を入れ替え
ています。
一番上が他サイト(当サイトの記事ですがテスト用サイトから呼んでいる)、2つめから下が自サイトのブログカードです。リンクをクリックすると同じタブで開きます。
CSS
.embed-wrapper { font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif; max-width: 500px; background-color: #fff; font-size: 13px; border: 1px solid rgba(0, 0, 0, 0.1); border-radius: 3px; background-clip: padding-box; box-sizing: border-box; } .embed-wrapper * { word-wrap: break-word; word-break: break-all; } .embed-wrapper-inner { padding: 12px; } .embed-header { position: relative; padding-left: 35px; height: 30px; margin-bottom: 5px; } .embed-header .blog-icon { position: absolute; top: 0; left: 0; width: 30px; height: 30px; border-radius: 30px; background-clip: padding-box; } .embed-header .blog-title, .embed-header .embed-header .blog-user { font-size: 12px; line-height: 1.3; overflow: hidden; max-height: 15px; } .embed-header .blog-title a, .embed-header .embed-header .blog-user a { color: #0e6ace; } .embed-header .blog-title { margin: 0; color: #0e6ace; margin-right: 110px; } .embed-header .blog-user { margin-right: 110px; } .embed-header .blog-user a { color: #6b7377; } .embed-logo { position: absolute; top: 0; right: 0; } .embed-logo .embed-logo-img { vertical-align: middle; opacity: .6; width: 100px; height: 18px; } .embed-content { position: relative; height: 100px; overflow: hidden; } .embed-content.with-thumb { min-height: 100px; } .embed-content.with-thumb .entry-body { margin-right: 110px; } .embed-content .thumb-wrapper { position: absolute; top: 0; right: 0; } .embed-content .thumb-wrapper .thumb { width: 100px; height: 100px; } .embed-content .entry-title { font-family: inherit; font-size: 17px; margin: 0 0 2px; line-height: 1.3; max-height: 47px; overflow: hidden; } .embed-content .entry-content { line-height: 1.5; font-size: 12px; max-height: 72px; overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; } .embed-footer { margin-top: 8px; height: 15px; position: relative; font-size: 11px; color: #6b7377; } .embed-footer a { color: #6b7377; } .embed-footer .updated { margin-right: .3em; } .embed-footer .star-count { padding-bottom: 1px; } .embed-footer img { vertical-align: middle; }こだわってオリジナルのものとまったく同じにしてみました。
よし、これを実装しよう!
); Array.prototype.forEach.call(iframes, function(iframe){ var embedUrl = reg.exec(iframe.src); if(embedUrl !== null){ iframe.src = ''; var url = decodeURIComponent(embedUrl[0]).replace('entry', 'embed'); var xhr = new XMLHttpRequest(); var parser = new DOMParser(); xhr.open('GET', url); xhr.send(); xhr.onreadystatechange = function() { if(xhr.readyState === 4 && xhr.status === 200) { var doc = parser.parseFromString(xhr.response, "text/html"); var blogcard = doc.getElementsByClassName('embed-wrapper')[0]; var element = blogcard.getElementsByTagName('time')[0]; element.removeAttribute('data-relative'); var links = blogcard.getElementsByTagName('a'); Array.prototype.forEach.call(links, function(link){ link.setAttribute('target', '_top'); }); iframe.parentNode.replaceChild(blogcard, iframe); } } } }); } })();
- ブログカードは記事内にしかありえませんから article タグに限定し、
- 複数あるかも知れない iframe を取り出し、
- ひとつひとつの iframe の src が自サイトであるかをチェックし、
- URL の entry を embed に差し替えて HTML ファイルを読み込み、
- DOM パースして
<div class="embed-wrapper"></div>
だけ取り出し、 - リンクターゲットを
_top
に差し替え、 - iframe と div を入れ替え
ています。
一番上が他サイト(当サイトの記事ですがテスト用サイトから呼んでいる)、2つめから下が自サイトのブログカードです。リンクをクリックすると同じタブで開きます。
03CSS
こだわってオリジナルのものとまったく同じにしてみました。
よし、これを実装しよう!