DOIリンク生成ツールをJavaScriptで作成！簡単コピー機能付き

## はじめに

学術分野で論文を探す際、多くの方が利用するのが **DOI（Digital Object Identifier）** です。DOIは、論文や学術資料を一意に識別するための仕組みで、通常のURLと異なり、**リンク切れの心配が少ない**のが特徴です。これは、DOIが固定された識別子として登録されており、資料のURLが変更されても新しいリンクへ自動的にリダイレクトされる仕組みがあるためです。

ただし、DOIからリンクを手動で生成するのは少々手間がかかります。そこで、**DOIを入力するだけでリンクを生成し、ワンクリックでクリップボードにコピーできるツール**を作成しました。このツールは、特別なソフトウェアを必要とせず、**ブラウザ上で簡単に使うことができる**のが特徴です。本記事では、このツールの作成手順とその使い方を説明します。


<br>

**作成したDOIリンク生成ツール：**
[https://mdown.ai/content/38ad2b57-c32b-402f-b8fc-d5761a55c873](https://mdown.ai/content/38ad2b57-c32b-402f-b8fc-d5761a55c873)  

## 作成したDOIリンク生成ツールの概要

このツールを使えば、次のような簡単な手順でDOIリンクを生成・コピーできます。

1. DOIを入力します（例：`10.1086/111605`）
2. 「リンクを生成」ボタンをクリックすると、対応するURL（`https://doi.org/`を付加したもの）が生成されます
3. 「クリップボードにコピー」ボタンをクリックすると、生成されたリンクを簡単にコピーできます
4. コピーが完了すると「コピーしました！」という表示とチェックマークが現れるので、操作の完了を確認できます

作成したツールのスクリーンショットや、実際に試すことができるリンクはこちらです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1599258/e6e55c29-96de-d9c4-5fa6-7ff42bca5b58.png)
[DOIリンク生成ツールを試す](https://mdown.ai/content/38ad2b57-c32b-402f-b8fc-d5761a55c873)  

<br>

このツールは、簡単にコンテンツを共有・公開できるプラットフォーム「[**Markdown AI**](https://mdown.com/ja/)」で公開しています。Markdown AIは、Markdown記法をベースに、HTML+CSS+JavaScriptやAIを活用したWebページを手軽に構築できる便利なツールです。Webページ作成が初めての方や、シンプルな操作で便利なツールやアイデアを公開したい方にも最適です。

## HTMLコード

以下は、ツール全体の構造を記述したHTMLコードです。このコードでは、入力フォーム、リンク生成ボタン、結果表示エリアを含む基本的なレイアウトを作成しています。

```html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8" />
  <meta
    name="viewport"
    content="width=device-width, initial-scale=1.0, minimum-scale=1.0"
  />
  <title>DOIリンクジェネレーター</title>
  <!-- Font Awesome（CDN） -->
  <link
    rel="stylesheet"
    href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css"
    integrity="sha512-Fo3rlrZj/k7ujTnHg4C+XcXuk8qVJkR3M+8u1XxClK5WQZFlEVkYlFHmraYzH7YgFZ4M1PAXwLkz5G1S/a5Zug=="
    crossorigin="anonymous"
    referrerpolicy="no-referrer"
  />
  <style>
    *, *::before, *::after {
      box-sizing: border-box;
    }
    body {
      margin: 0;
      padding: 0;
      font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
      background-color: #eef2f5;
    }
    .container {
      width: 100%;
      max-width: 500px;
      margin: 20px auto;
      background: #fff;
      padding: 20px 15px;
      border-radius: 10px;
      box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
    }
    h1 {
      text-align: center;
      color: #2c3e50;
      margin-bottom: 15px;
      font-size: 1.6rem;
    }
    .instructions {
      font-size: 1rem;
      color: #34495e;
      margin-bottom: 15px;
      text-align: center;
    }
    .input-group {
      display: flex;
      flex-direction: column;
      margin-bottom: 15px;
    }
    .input-group label {
      margin-bottom: 5px;
      font-weight: bold;
      color: #2c3e50;
    }
    input[type="text"] {
      width: 100%;
      padding: 10px 12px;
      border: 1px solid #bdc3c7;
      border-radius: 5px;
      font-size: 1rem;
    }
    button.generate-btn {
      width: 100%;
      padding: 12px;
      background-color: #3498db;
      color: #fff;
      border: none;
      border-radius: 5px;
      font-size: 1rem;
      cursor: pointer;
      transition: background-color 0.3s ease;
      margin-top: 10px;
    }
    button.generate-btn:hover {
      background-color: #2980b9;
    }

    /* 結果表示領域 */
    .result {
      margin-top: 20px;
      word-wrap: break-word;
    }
    .link-label {
      font-weight: bold;
      color: #2c3e50;
      margin-bottom: 5px;
    }
    .result a {
      color: #2980b9;
      text-decoration: none;
    }
    .external-link-icon {
      margin-left: 6px;
      font-size: 0.9rem;
      vertical-align: middle;
    }

    /* コピー用ボタンのスタイル */
    .copy-button {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      background-color: #2ecc71;
      color: #fff;
      border: none;
      border-radius: 5px;
      cursor: pointer;
      font-size: 0.85rem;
      position: relative;
      margin-top: 10px;
      padding: 6px 10px;
      /* ボタンの幅が変わりにくいように最小幅を設定 */
      min-width: 180px;
      transition: background-color 0.3s ease;
    }
    .copy-button:hover {
      background-color: #27ae60;
    }

    /* 通常表示/コピー後表示の切り替え */
    .default-text, .default-icon {
      display: inline-block;
    }
    .copied-text, .copied-icon {
      display: none;
    }
    .copy-button.copied .default-text,
    .copy-button.copied .default-icon {
      display: none;
    }
    .copy-button.copied .copied-text,
    .copy-button.copied .copied-icon {
      display: inline-block;
    }

    .error {
      color: #e74c3c;
      text-align: center;
      margin-top: 10px;
    }

    /* スマホ向けの調整 */
    @media (max-width: 600px) {
      .container {
        padding: 15px 10px;
      }
      h1 {
        font-size: 1.4rem;
      }
      .instructions {
        font-size: 0.95rem;
      }
      input[type="text"] {
        font-size: 0.95rem;
      }
      button.generate-btn {
        font-size: 0.95rem;
        padding: 10px;
      }
      .copy-button {
        font-size: 0.8rem;
        padding: 6px 8px;
      }
    }
  </style>
</head>
<body>
  <div class="container">
    <h1>DOIリンクジェネレーター</h1>
    <p class="instructions">
      以下に正しい形式のDOIを入力すると、リンクを生成します。<br />
      <strong>※</strong>このツールでは、DOIが実在するかどうかの検証は行いません。<br />
      実在性を確認したい場合は、<a href="https://dx.doi.org/" target="_blank" rel="noopener noreferrer">dx.doi.org</a> などをご利用ください。<br />
      <br />
      例：<code>10.1086/111605</code>
    </p>

    <!-- 入力フォーム -->
    <form onsubmit="generateLink(); return false;">
      <div class="input-group">
        <label for="doiInput">DOI:</label>
        <input
          type="text"
          id="doiInput"
          placeholder="例: 10.1086/111605"
        />
      </div>
      <button type="submit" class="generate-btn">リンクを生成</button>
    </form>

    <!-- 結果表示エリア -->
    <div id="result" class="result"></div>
  </div>

  <script>
    /**
     * DOI形式を正規表現でチェック
     * 「10.」で始まり、4〜9桁の数字 + 「/」 + 接尾辞(英数字や特定の記号)を含む形式
     */
    function validateDOI(input) {
      const doiPattern = /^10\.\d{4,9}\/[-._;()/:A-Z0-9]+$/i;
      return doiPattern.test(input);
    }

    /**
     * リンク生成メイン関数
     */
    function generateLink() {
      const doiInput = document.getElementById('doiInput').value.trim();
      const resultDiv = document.getElementById('result');

      // クリア
      resultDiv.innerHTML = '';

      // 入力チェック
      if (!doiInput) {
        resultDiv.innerHTML = '<p class="error">DOIを入力してください。</p>';
        return;
      }
      if (!validateDOI(doiInput)) {
        resultDiv.innerHTML = `
          <p class="error">DOI形式が正しくありません。以下の形式で入力してください：</p>
          <ul class="error" style="list-style: none; padding-left: 0;">
            <li>・DOIは「10.」で始まります。</li>
            <li>・「/」で区切られた接尾辞を含む必要があります。</li>
            <li>・例: <code>10.1086/111605</code></li>
          </ul>
        `;
        return;
      }

      // 正しい形式の場合、リンクを生成
      const doiLink = `https://doi.org/${doiInput}`;
      
      // 余計な改行やインデントを入れないよう、1行でinnerHTMLを設定
      resultDiv.innerHTML = `<p class="link-label">生成されたリンク:</p><p><a href="${doiLink}" target="_blank" rel="noopener noreferrer">${doiLink}<i class="fas fa-external-link-alt external-link-icon"></i></a></p><button class="copy-button" onclick="copyToClipboard(this, '${doiLink}')"><span class="default-text">クリップボードにコピー</span><i class="fas fa-copy default-icon"></i><span class="copied-text">コピーしました！</span><i class="fas fa-check copied-icon"></i></button>`;
    }

    /**
     * テキストコピー関数
     */
    function copyToClipboard(button, text) {
      navigator.clipboard.writeText(text)
        .then(() => {
          button.classList.add("copied");
          // 2秒後に元に戻す
          setTimeout(() => {
            button.classList.remove("copied");
          }, 2000);
        })
        .catch(err => {
          console.error("コピーに失敗しました:", err);
        });
    }
  </script>
</body>
</html>
```

## ツールの技術解説

ツールは以下の技術で構成されています。
- **HTML**: ツールの基本構造を作成
- **CSS**: レスポンシブデザインを含むスタイルを定義
- **JavaScript**: DOIの検証やリンク生成、クリップボードコピー機能を実装

また、正規表現を使用してDOIの形式チェックを行うなど、使い勝手を考慮した設計になっています。

## まとめ

このツールを使うことで、DOIリンクを簡単かつ効率的に生成・管理できます。学術分野に携わる方にとって、DOIを活用した作業の手間を省く役立つツールです。

また、Markdown AIを活用すれば、同様のツールや記事を簡単に作成・公開できるので、ぜひ活用してみてください。

## 参考資料

https://mdown.com/ja/