LoginSignup
0
0

More than 1 year has passed since last update.

microCMSのコンテンツをmarkdownファイルで取得する方法

Last updated at Posted at 2021-10-12

microCMSのAPIでコンテンツを取得して、それぞれエンドポイントごとに個別のファイルを作成する必要ことがあった。取得したファイルを編集するため、HTMLではなく、markdownファイルで取得する必要があった。その時の記録を残しておく。
なお、npmは使わず、CDNのみを利用するため、Nodeやwebpackがわからない人もこの方法で取得できる。

microCMS

まずは、microCMSのAPI取得である。公式ドキュメントにもあるように、serviceDomainapiKey を利用して取得できる。このapiKeyには2種類でもある。X-API-KEYとX-GLOBAL-DRAFT-KEYである。
GETによる取得は前者のX-API-KEYを利用し、下書きコンテンツも含めて取得する場合はX-GLOBAL-DRAFT-KEYを利用する。

今回はX-API-KEYを利用する。
まずは、htmlのCDNでmicroCMSを読み込み、jsファイルにimportする。jsファイルではclientでドメインとAPIキーと共に初期化する。

index.html
<script src="https://unpkg.com/microcms-js-sdk@latest/dist/umd/microcms-js-sdk.js"></script>
main.js
const { createClient } = microcms;
const client = createClient({
  serviceDomain: "ドメイン",
  apiKey: "ご自身のX-API-KEY"
  });

次に、GET /api/v1/{endpoint} の形式で取得する。client.getではendpointに配列からそれぞれの値を取得する。取得したオブジェクトは定数materialContentsに保存する。awaitで記述するのはこの関数を次に、関数でasyncを定義しているからだ。

main.js
const endpointArray = ['category1','category2','category3'];
const category = endpointArray[1];
const data = await client.get({
  endpoint: category,
  queries: {
    offset,
    limit
  }
})

const materialContents = data.contents;

materialContents に保存するオブジェクト内に必要なデータはタイトル、記述したコンテンツブロックである。以下のようにオブジェクトは取得できる。
object.jpg

turndownService

取得したHTMLをmarkdown化するのが Turndown というモジュールである。

これもCDNで利用できる。下にあるCDNはこのTurndownのプラグインでこれがあることでテーブルタグもhtmlからmarkdown表記に変更できる

index.html
    <script src="https://unpkg.com/turndown/dist/turndown.js"></script>
    <script src="https://unpkg.com/turndown-plugin-gfm/dist/turndown-plugin-gfm.js"></script>

このturndownを利用して、以下のようなソースコードで取得して、その内容をマークダウン化した。
取得したオブジェクトからタイトルを取得して変数に代入する。その後、contentの配列は三項演算子でrichEditorかhtmlかで取得する内容を変更している。それらをDOMでタイトルはpタグにコンテンツブロックの内容は一つの記事ごとにまとめてdivタグに代入している。そして、タイトルに合わせた記事内容が表記されるようにappendChildでそれぞれの内容の結合を行った後、それをturndownでmarkdownにしている。

const { createClient } = microcms;
const gfm = turndownPluginGfm.gfm;
let turndownService = new TurndownService({ headingStyle: 'atx' , codeBlockStyle: 'fenced', preformattedCode: 'true'});
turndownService.use(gfm);
// いくつかのoptionがある。headingStyle: 'atx'h2が##で表示される
const client = createClient({
  serviceDomain: env.Domain,
  apiKey: env.apiKey
  });
  const endpointArray = ['category1','category2','category3','category4','category5'];

const getAllContents = async (limit=100, offset=0) => {
  const category = endpointArray[0];//好きなendpointのカテゴリを指定する
  const data = await client.get({
    endpoint: category,
    queries: {
      offset,
      limit
    }
  })
  const materialContents = data.contents;

  const mainContent = document.getElementById("mainContent");
  materialContents.forEach(element => {
    const p = document.createElement("p");
    const div = document.createElement("div");
    let title = `# ${element.title}`;
    let chapterContets = "";
    for (let i = 0; i < element.content.length ; i++) {
      if(element.content[i]) {
        let codeBlock = (element.content[i].richEditor) ? element.content[i].richEditor : element.content[i].html;
        chapterContets += codeBlock; //各コンテンツごとに変数に格納。reduceで書いたもよかった気がする。
      }
      div.innerHTML = chapterContets;
    }
    p.innerHTML = title;
    p.appendChild(div);
    mainContent.appendChild(p);
    //mainContentに取得したデータが全て格納されている。
  });

let mainMd = turndownService.turndown(mainContent);

blob

最後に、blobを用いて、htmlからmarkdown化させたmicroCMSの内容をファイルとしてダウンロードする。blobはインスタンス化する際に第1引数に変換する対象、第2引数にその形式を当てはめる。
本来はmd拡張子にしたかったが、確認できなかったため、txt取得する。もちろんファイルの中身はhtmlをそのままmarkdown化させているので大きな問題はない。
また、目的としてファイルダウンロードができれば、問題ないのでブラウザでhtmlを開いたら、目的のエンドポイントごとにmarkdown化されたファイルを取得できるようにした。
それを踏まえたのが下記のようなコードである。microCMSから取得したデータが格納されたpタグを生成した mainContent をまず、marakdown化して、その内容をblobで変換している。

main.js
const { createClient } = microcms;
const gfm = turndownPluginGfm.gfm;
let turndownService = new TurndownService({ headingStyle: 'atx' , codeBlockStyle: 'fenced', preformattedCode: 'true'});
turndownService.use(gfm);
// headingStyle: 'atx'h2が##で表示される
const client = createClient({
  serviceDomain: env.Domain,
  apiKey: env.apiKey
  });
const endpointArray = ['category1','category2','category3','category4','category5'];

const getAllContents = async (limit=100, offset=0) => {
  const category = endpointArray[0];
  const data = await client.get({
    endpoint: category,
    queries: {
      offset,
      limit
    }
  })
  const materialContents = data.contents;
  const mainContent = document.getElementById("mainContent");
  materialContents.forEach(element => {
    const p = document.createElement("p");
    const div = document.createElement("div");
    let title = `# ${element.title}`;
    let chapterContets = "";
    for (let i = 0; i < element.content.length ; i++) {
      if(element.content[i]) {
        let codeBlock = (element.content[i].richEditor) ? element.content[i].richEditor : element.content[i].html;
        chapterContets += codeBlock; 
      }
      div.innerHTML = chapterContets;
    }
    p.innerHTML = title;
    p.appendChild(div);
    mainContent.appendChild(p);
    //mainContentに取得したデータが全て格納されている。
  });

  let mainMd = turndownService.turndown(mainContent);
  const blob = new Blob([mainMd],{type: 'text/plain' });
  const link = document.createElement('a');
  link.href = URL.createObjectURL(blob);
  link.download = `${category}.txt`;
  link.click();

  if (data.offset + data.limit < data.totalCount) {
    const contents = await getAllContents(data.limit, data.offset + data.limit)
    return [ ...data.contents, ...contents ]
  }
  return data.contents
}
getAllContents();

まとめ

このように、microCMSのAPIを元になかなか行わないであろうHTMlからmarkdownファイルへの変換を行うことができた。また、CDNなのでnpmでNode環境を利用しないことも簡潔で良いだろう。ただ、ネストを深めれば、カテゴリ用の配列から手動で行わずにファイルを取得する方法もあったり、無駄に冗長になった処理もあるのでコードのシェイプアップする必要はある。
こちらがgithubのソースコードである。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0