マニュアル

カスタムスクリプトの仕様

カスタムブロックを作成する際に設定できる「カスタムスクリプト」の仕様は以下の通りです。

カスタムブロックで入力されたコンテンツは、記事(ウェブページ)編集画面 iframe の body 内に埋め込まれて表示されます(入力された内容がそのまま出力されます)。
カスタムスクリプトでは以下の2つのことを実現することができます。

  • iframe で表示した際のスタイルの変更
  • 出力される HTML の変更

「iframe で表示した際のスタイルの変更」について

例えば、以下のような内容を「カスタムスクリプト」項目に挿入すると、記事(ウェブページ)編集画面での表示時にはフォントが Noto Sans JP で表示されます。

<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@100&display=swap" rel="stylesheet">
<style type="text/css">
body { font-family: 'Noto Sans JP', sans-serif; }
</style>

「カスタムスクリプト」の項目は、必ずしも JavaScript で記載する必要はありません。
CSS での調整であっても、上記の「カスタムスクリプト」を設定した記事(ウェブページ)編集画面で作成したコンテンツを出力するテンプレートにて、以下のように記述していただければ、記事(ウェブページ)編集画面と公開されたコンテンツで同じフォントを利用することになり、記事(ウェブページ)編集画面上でも公開後のページがイメージしやすくなります。

<head>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@100&display=swap" rel="stylesheet">
<style type="text/css"> .noto-sans { font-family: 'Noto Sans JP', sans-serif; } </style>
</head>
<!-- このブロックの識別子が noto_sans であるものとします -->
<mt:BlockEditorBlocks tag="EntryBody">
<mt:If name="type" eq="custom-noto_sans">
<div class="noto-sans"><mt:Var name="__value__" /></div>
<mt:Else>
<mt:Var name="__value__" />
</mt:If>
</mt:BlockEditorBlocks>

「出力される HTML の変更」について

前述のように、「カスタムスクリプト」項目では CSS のみでも調整が可能ですが、JavaScript の API を利用するとより柔軟に、出力する HTML を任意の内容に置き換えることができます。
カスタムブロック機能を利用して高機能な Markdown を利用する」でも紹介しているマークダウンを適用する例が、以下のカスタムスクリプトになります。

<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/1.1.0/marked.min.js" integrity="sha256-POA+Q3FC8tyo/jZhQrw40H5mKcWAABdxNeUQ/uhIm4U=" crossorigin="anonymous"></script>
<script>
document.addEventListener("DOMContentLoaded", () => {
  if (document.body.dataset.hasCompiledHtml) {
    return;
  }

  const source = document.querySelector(".source").innerHTML;
  MTBlockEditorSetCompiledHtml(marked(source));
});
</script>

MTBlockEditorSetCompiledHtml(html) を呼び出すと、出力される HTML を指定することができます。
また、編集中の IFRAME 内の内容もここで指定した HTML に置き換えられます。その結果としてこのカスタムスクリプトは、「入力内容のHTML」と「出力されるHTML」の両方で評価されます。
「出力されるHTML」で表示された場合には「document.body.dataset.hasCompiledHtml」の値が真になります。

具体的には、入力内容のHTMLの時には以下の内容で評価されることでHTMLが置き換えられ、

<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/1.1.0/marked.min.js" integrity="sha256-POA+Q3FC8tyo/jZhQrw40H5mKcWAABdxNeUQ/uhIm4U=" crossorigin="anonymous"></script>
<script>
document.addEventListener("DOMContentLoaded", () => {
  const source = document.querySelector(".source").innerHTML;
  MTBlockEditorSetCompiledHtml(marked(source));
});
</script>

出力される HTML の時には以下の内容で評価され(何も実行されず)出力される HTML が iframe 内に表示される、という形になります。

<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/1.1.0/marked.min.js" integrity="sha256-POA+Q3FC8tyo/jZhQrw40H5mKcWAABdxNeUQ/uhIm4U=" crossorigin="anonymous"></script>
<script>
document.addEventListener("DOMContentLoaded", () => {
  return;
});
</script>

「ファイルを読み込むAPI」について

MTBlockEditorAddDroppable(callback) を使うと、カスタムスクリプトの中でファイルを読み込むことができます。

MTBlockEditorAddDroppable(callback) を呼び出すと編集中のブロック全体がドラッグアンドドロップの領域になり、またブロックをクリックした場合にはファイルの選択ダイアログが表示されるようになります。
ファイルが選択されるとコールバックの関数が呼ばれます。コールバックには、ドラッグアンドドロップの場合にはdropイベントが、クリックからの選択の場合にはchangeイベントが渡されるので、イベントオブジェクトからファイルを取得して内容を読み込むことができます。

以下はCSVファイルを読み込んでHTMLのテーブルとして挿入する例になります。

<script>
document.addEventListener("DOMContentLoaded", async () => {
  if (!document.body.dataset.hasCompiledHtml) {
    document.body.textContent = "CSVファイルをドロップしてください";
    Object.assign(document.body.style, {
      textAlign: "center",
      paddingTop: "40px",
    });
  }

  MTBlockEditorAddDroppable((ev) => {
    const files =
      ev.type === "change" ? ev.target.files : ev.dataTransfer.files;
    for (let i = 0; i < files.length; i++) {
        const reader = new FileReader();
        reader.onload = (e) => {
          const data = e.target.result;
          const tbody = data.split("\n").map((line, i) => {
            const tagName = i === 0 ? "th" : "td";
            return "<tr>" + line.split(",").map((d) => `<${tagName}>${d}</${tagName}>`).join("") + "</tr>"
          }).join("");
          MTBlockEditorSetCompiledHtml(`<table>${tbody}</table>`);
        };
        reader.readAsText(files[i]);
    }
  });
});
</script>

このAPIは「【カスタムブロック】エクセルを読み込んでテーブルで表示する」でも利用しています。

カスタムスクリプトを使うか、mt:BlockEditorBlocks を使うか

カスタムスクリプトと mt:BlockEditorBlocks では「出力の加工」を行うことができ、加工内容によってはどちらの方法でも同じ結果を得られます。同じ結果を得ることができるケースは、カスタムスクリプトが「編集時にブラウザで処理されるので、後からカスタムスクリプトを変更しても出力内容は変更されない(後から変更しても再編集を行わなければ投稿済みの古いデータへの影響はない)」というものであり、mt:BlockEditorBlocks を使った MTML での加工では「MTML の変更で後から出力内容が変更できる」という特徴があるので、その点を踏まえてどちらの方法を採用するか検討をすることをおすすめします。

それぞれの方法でのできること、できないことについては以下のような違いがあります。

カスタムスクリプト

  • JavaScript で複雑な加工を行うことができる
  • 編集中のプレビューでも出力と同じ結果を表示することができる

mt:BlockEditorBlocks

  • MTタグを組み合わせたカスタマイズを行うことができる
  • 1つのソースから、複数の出力を得ることができる
    AMP対応の出力を行うケースなど