SharePointリストのアイテムをニュース風にカスタマイズ

# はじめに
本記事は基本的なリストの使い方を理解していて、書式設定もある程度使える人向けにまとめています。

もし、リストは分かるけど、書式設定はちょっと…という方は、
[SharePointリストの書式設定(JSON) チートシート](https://qiita.com/Momomo_ai/items/58bf768fb83bddfbdca1)
でまとめたチートシートをご参考に是非チャレンジして見てください。

# 背景
リストを作成した際に、ニュースっぽくサイトのページに載せたい。
こんな感じの奴。
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239956/b7b3cdae-0587-943f-5053-00f7e9278e3d.png">

書式設定で簡単に使いまわせるものがあると嬉しいな。
よし、せっかくチートシートも作ったので、作ってみよう。が背景です。

# 1. リストの定義列
|内部名|列名|種類
|:---|:---|:---
|Title|タイトル| １行テキスト
|Modified|更新日時| 日付と時刻
|Author|登録者| ユーザーまたはグループ
|Detail|記事|複数行テキスト(書式なしテキスト)
|theme|テーマ|選択肢

※ 「記事」と「テーマ」のみ作成が必要です

# 2. 画面構成

**タイル表示の時**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239956/4d27db2f-3e25-0a25-59fa-8805fe09e211.png)


**リスト表示の時**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239956/9f0fa725-d3f2-eff9-f462-ded42792b71b.png)

リスト表示にすると少しだけ全体の文字が大きくなります。

**画面操作**
 ![ニュース風.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239956/825bc0ff-50f8-6440-7e41-9071b1a6f825.gif)


# 3. 書式設定
列を定義したら、ビューの書式設定に以下のコードを張り付けます。
「保存」したら、ビューの表示形式の一覧に「タイル」が出現します。（デフォルトは非表示）

```json
{
  "$schema": "https://developer.microsoft.com/json-schemas/sp/view-formatting.schema.json",
  "hideColumnHeader": true,
  "hideSelection": true,
  "tileProps": {
    "hideColumnHeader": true,
    "hideSelection": false,
    "height": "250",
    "width": "240",
    "formatter": {
      "elmType": "div",
      "children": [
        {
          "elmType": "div",
          "style": {
            "display": "flex",
            "flex-direction": "column",
            "box-shadow": "2px 2px 4px gray",
            "height": "240px",
            "width": "235px"
          },
          "children": [
            {
              "elmType": "div",
              "style": {
                "display": "flex",
                "flex-direction": "flex-start",
                "height": "30px",
                "background-color": "#2b2c34",
                "color": "#fffffe",
                "box-sizing": "border-box",
                "padding": "2px 5px"
              },
              "children": [
                {
                  "elmType": "div",
                  "style": {
                    "display": "inline-block",
                    "font-size": "20px",
                    "padding": "5px",
                    "padding-top": "2px"
                  },
                  "attributes": {
                    "iconName": "News"
                  }
                },
                {
                  "elmType": "div",
                  "txtContent": "=getYear([$Created])+'.'+toString(Number(getMonth([$Created]))+1) +'.'+getDate([$Created])",
                  "style": {
                    "display": "inline-block",
                    "padding": "2px",
                    "font-size": "15px"
                  },
                  "attributes": {
                    "class": "ms-fontSize-s ms-fontWeight-bold"
                  }
                }
              ]
            },
            {
              "elmType": "div",
              "txtContent": "[$Title]",
              "style": {
                "width": "100%",
                "height": "50px",
                "box-sizing": "border-box",
                "background-color": "#eebbc3",
                "color": "#232946",
                "border-style": "none",
                "overflow": "hidden",
                "padding": "3px 10px 0px 10px"
              },
              "attributes": {
                "class": "ms-fontSize-m ms-fontWeight-bold"
              }
            },
            {
              "elmType": "div",
              "style": {
                "width": "100%",
                "height": "130px",
                "display": "flex",
                "flex-direction": "column",
                "background-color": "#fffffe"
              },
              "children": [
                {
                  "elmType": "div",
                  "txtContent": "='< ' +[$theme] + ' >'",
                  "style": {
                    "border-style": "none",
                    "max-height": "30px",
                    "overflow": "hidden",
                    "padding": "2px 15px"
                  },
                  "attributes": {
                    "class": "ms-fontSize-s ms-fontWeight-bold"
                  }
                },
                {
                  "elmType": "div",
                  "txtContent": "=[$Detail]",
                  "style": {
                    "background-color": "transparent",
                    "border-style": "none",
                    "color": "#777",
                    "overflow": "hidden",
                    "width": "100%",
                    "height": "100px",
                    "box-sizing": "border-box",
                    "padding": "10px 10px",
                    "margin-bottom": "10px"
                  },
                  "attributes": {
                    "class": "ms-fontSize-s"
                  }
                }
              ]
            },
            {
              "elmType": "div",
              "txtContent": "='by '+[$Author.title]",
              "style": {
                "width": "100%",
                "height": "25px",
                "box-sizing": "border-box",
                "padding": "3px 15px",
                "color": "#2b2c34",
                "background-color": "#fffffe",
                "border-style": "none",
                "text-align": "right"
              },
              "attributes": {
                "class": "ms-fontSize-s"
              }
            }
          ]
        }
      ]
    }
  },
  "rowFormatter": {
    "elmType": "button",
    "customRowAction": {
      "action": "defaultClick"
    },
    "style":{
      "height": "250",
      "width": "100%",
      "margin":"10px",
      "padding": "0",
      "border-style":"none",
      "cursor": "default"
    },
    "children": [
      {
        "elmType": "div",
        "style": {
          "display": "flex",
          "flex-direction": "column",
          "box-shadow": "2px 2px 4px gray",
          "height": "240px",
          "width": "100%"
        },
        "children": [
          {
            "elmType": "div",
            "style": {
              "display": "flex",
              "flex-direction": "flex-start",
              "height": "30px",
              "background-color": "#2b2c34",
              "color": "#fffffe",
              "box-sizing": "border-box",
              "padding": "2px 5px"
            },
            "children": [
              {
                "elmType": "div",
                "style": {
                  "display": "inline-block",
                  "font-size": "20px",
                  "padding": "5px",
                  "padding-top": "2px"
                },
                "attributes": {
                  "iconName": "News"
                }
              },
              {
                "elmType": "div",
                "txtContent": "=getYear([$Created])+'.'+toString(Number(getMonth([$Created]))+1) +'.'+getDate([$Created])",
                "style": {
                  "display": "inline-block",
                  "padding": "2px",
                  "font-size": "15px"
                },
                "attributes": {
                  "class": "ms-fontSize-s ms-fontWeight-bold"
                }
              }
            ]
          },
          {
            "elmType": "div",
            "txtContent": "[$Title]",
            "style": {
              "width": "100%",
              "height": "50px",
              "text-align": "left",
              "box-sizing": "border-box",
              "background-color": "#eebbc3",
              "color": "#232946",
              "border-style": "none",
              "overflow": "hidden",
              "padding": "3px 10px 0px 10px"
            },
            "attributes": {
              "class": "ms-fontSize-l ms-fontWeight-bold"
            }
          },
          {
            "elmType": "div",
            "style": {
              "width": "100%",
              "height": "130px",
              "display": "flex",
              "flex-direction": "column",
              "background-color": "#fffffe"
            },
            "children": [
              {
                "elmType": "div",
                "txtContent": "='< ' +[$theme] + ' >'",
                "style": {
                  "border-style": "none",
                  "text-align": "left",
                  "max-height": "30px",
                  "overflow": "hidden",
                  "padding": "2px 15px"
                },
                "attributes": {
                  "class": "ms-fontSize-m ms-fontWeight-bold"
                }
              },
              {
                "elmType": "div",
                "txtContent": "=[$Detail]",
                "style": {
                  "background-color": "transparent",
                  "border-style": "none",
                  "text-align": "left",
                  "color": "#777",
                  "overflow": "hidden",
                  "width": "100%",
                  "height": "100px",
                  "box-sizing": "border-box",
                  "padding": "10px 10px",
                  "margin-bottom": "10px"
                },
                "attributes": {
                  "class": "ms-fontSize-m"
                }
              }
            ]
          },
          {
            "elmType": "div",
            "txtContent": "='by '+[$Author.title]",
            "style": {
              "width": "100%",
              "height": "25px",
              "box-sizing": "border-box",
              "padding": "3px 15px",
              "color": "#2b2c34",
              "background-color": "#fffffe",
              "border-style": "none",
              "text-align": "right"
            },
            "attributes": {
              "class": "ms-fontSize-s"
            }
          }
        ]
      }
    ]
  }
}
```
# 今後の課題
作っていく上で悩んだポイントや、今後改善していきたいところを箇条書き

+ 複数行テキスト(書式あり)だとエスケープされる
    + txtContent()で出力すると\<h1>などがそのまま出力されちゃう
    + 何とか文字だけ抽出して出力するような仕組みを考えたい
+ HTMLからjsonに変換するツールが欲しい
    + 書いてる内容はほぼHTML
    + json形式で書き始めたら、結構しんどかった。