<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF xmlns="http://purl.org/rss/1.0/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel rdf:about="https://let.hatelabo.jp/yanbe/rss">
    <link>https://let.hatelabo.jp/yanbe/rss</link>
    <description></description>
    <title>Bookmarklets from yanbe</title>
    <items>
      <rdf:Seq>
        <rdf:li rdf:resource="https://let.hatelabo.jp/yanbe/let/hLHUs-LCx5cm"/>
      </rdf:Seq>
    </items>
  </channel>
  <item rdf:about="https://let.hatelabo.jp/yanbe/let/hLHUs-LCx5cm">
    <link>https://let.hatelabo.jp/yanbe/let/hLHUs-LCx5cm</link>
    <dc:date>2018-02-23T00:23:15Z</dc:date>
    <description>はてなリンク記法をa要素に展開します。つまり [http://b.hatena.ne.jp/:title=hoge]  等を &lt;a href="http://b.hatena.ne.jp/"&gt;hoge&lt;/a&gt; に変換します。</description>
    <dc:creator>yanbe</dc:creator>
    <title>[Let] はてなリンク記法を展開</title>
    <content:encoded>&lt;a href="javascript:%22https%3A%2F%2Flet.st-hatelabo.com%2Fyanbe%2Flet%2FhLHUs-LCx5cm.bookmarklet.js%20%28arg%29%22.replace%28%2F%28%5CS%2B%29%5Cs%2B%28%5CS%2A%29%2F%2Cfunction%28s%2Curl%2Carg%29%7Bs%3Ddocument.createElement%28%22script%22%29%3Bs.charset%3D%22utf-8%22%3Bs.src%3Durl%2B%22%3Fs%3D%22%2BencodeURIComponent%28arg%29%3Bdocument.body.appendChild%28s%29%7D%29%3Bvoid%280%29%3B"&gt;はてなリンク記法を展開&lt;/a&gt;&lt;pre&gt;/*
 * @title はてなリンク記法を展開
 * @description はてなリンク記法をa要素に展開します。つまり [http://b.hatena.ne.jp/:title=hoge]  等を &amp;lt;a href=&amp;quot;http://b.hatena.ne.jp/&amp;quot;&amp;gt;hoge&amp;lt;/a&amp;gt; に変換します。
 * @include http://blog.hatena.ne.jp/*
 * @license MIT License
 * @require
 */

function getHatenaLinkNotationOnCursor(textarea) {
  var text = textarea.value;
  var caret = textarea.selectionStart;
  var start = text.lastIndexOf('[', caret);
  var end = text.indexOf(']', caret-1);
  var notation = text.substring(start, end+1);
  return notation.indexOf('\n') != -1 ? undefined : { notation: notation, start: start, end: end };
}

function parseHatenaLinkNotation(notation) {
  var notation_str = notation.notation;
  var result = { notation: notation };
  var m_url = notation_str.match(/https?:\/\/[^:\]]+/);
  if (m_url) {
     result['url'] = m_url[0];
  }
  var m_title = notation_str.match(/:title(?:=([^:\]]+))?/);  //  [http://b.hatena.ne.jp/:title=hoge]
  if (m_title) {
     result['title'] = m_title[1] ? m_title[1] : true;
  }
  var m_bookmark = notation_str.match(/:bookmark]/);  //  [http://b.hatena.ne.jp/:title=hoge:bookmark]
  if (m_bookmark) {
     result['bookmark'] = true;
  }

  var m_embed = notation_str.match(/:embed(:cite)?]$/);  // [http://b.hatena.ne.jp/:embed:cite]
  if (m_embed) {
     result['embed'] = true;
     if (m_embed[1]) {
        result['cite'] = true;
     }
  }
  return result;
}

function expandSimpleHatenaLinkNotation(result) {
  var a = document.createElement('a');
  a.setAttribute('data-snf-link', 'keep');
  a.href = result['url'];
  if (result['title']) {
    if (typeof(result['title']) == 'string') {
      a.innerHTML = result['title'];
    } else {
      a.innerHTML = result['title'];
    }
  } else {
    a.innerHTML = result['url'];
  }
  var frag = document.createDocumentFragment();
  frag.appendChild(a);

  if (result['bookmark']) {
    var bookmarkLink = document.createElement('a');
    bookmarkLink.href = 'http://b.hatena.ne.jp/entry/' + result['url'];
    bookmarkLink.className = 'http-bookmark';

    var bookmarkCount = document.createElement('img');
    bookmarkCount.src = '//b.hatena.ne.jp/entry/image/' + result['url'];
    bookmarkCount.className = 'http-bookmark';

    bookmarkLink.appendChild(bookmarkCount);
    frag.appendChild(bookmarkLink);
  }
  return frag;
}

function expandEmbedHatenaLinkNotation(result) {
  var iframe = document.createElement('iframe');
  iframe.setAttribute('data-snf-link', 'keep');
  iframe.src = 'https://hatenablog-parts.com/embed?url=' + encodeURIComponent(result['url']);
  iframe.title = result['title'];
  iframe.className = 'embed-card embed-blogcard';
  iframe.scrolling = 'no';
  iframe.frameBorder = '0';
  iframe.style.display = 'block';
  iframe.style.width = '100%';
  iframe.style.height = '190px';
  iframe.style.maxWidth = '500px';
  iframe.style.margin = '10px 0px';
  var frag = document.createDocumentFragment();
  frag.appendChild(iframe);
  if (result['cite']) {
    var cite = document.createElement('cite');
    cite.className = 'hatena-citation';
    var citeLink = document.createElement('a');
    citeLink.href = result['url'];
    citeLink.innerHTML = new URL(result['url']).hostname;
    cite.appendChild(citeLink);
    frag.appendChild(cite);
  }
  return frag;
}

function expandHatenaLinkNotation(result, textarea) {
  var expanded = result['embed'] ? expandEmbedHatenaLinkNotation(result) : expandSimpleHatenaLinkNotation(result);
  var notation = result['notation'];
  var comment = document.createComment(notation['notation']);
  var div = document.createElement('div');
  div.appendChild(comment);
  div.appendChild(expanded);
  var replaceHTML = div.innerHTML;
  var text = textarea.value;
  textarea.value = text.substring(0, notation['start']) + replaceHTML + text.substring(notation['end']+1);
}

function main() {
  var textarea = document.querySelector('textarea.editor-body-textarea') ;
  if (!textarea) return;
  var notation = getHatenaLinkNotationOnCursor(textarea);
  if (!notation) return;
  var result = parseHatenaLinkNotation(notation);
  if (!result['url']) return;
  if (typeof(result['title']) == 'string') {
    expandHatenaLinkNotation(result, textarea);
  } else {
    var syntax = '[' + result['url'] + ':title]';
    $.ajax({
      url: 'http://blog.hatena.ne.jp/api/external/json?url='+encodeURIComponent('http://d.hatena.ne.jp/api/syntax?syntax=' + encodeURIComponent(syntax))
    }).done(function(json) {
      var div = document.createElement('div');
      div.innerHTML = json[syntax];
      result['title'] = div.firstChild.innerHTML;
    }).fail(function() {
      result['title'] = 'ここにタイトルを入力';
    }).always(function () {
      expandHatenaLinkNotation(result, textarea);
    });
  }
}

main();&lt;/pre&gt;</content:encoded>
  </item>
</rdf:RDF>
