コンテンツにスキップ

リッチテキストの形(Hako Rich Text v1)

リッチエディタのフィールドの値は、Hako Rich Text v1 という形の JSON で読み書きします。形は ProseMirror と Tiptap の JSON(type attrs content marks text)と同じです。Tiptap の generateHTML などに、変えずにそのまま渡せます。

場面 形
Content API で読む 既定でこの形(正規形)。richText=html を付けると HTML の文字列
Content API と Admin API で書く この形の JSON か、HTML の文字列
{
"type": "doc",
"content": [
{
"type": "heading",
"attrs": { "level": 2 },
"content": [{ "type": "text", "text": "はじめに" }]
},
{
"type": "paragraph",
"content": [
{ "type": "text", "text": "これは" },
{ "type": "text", "text": "太字", "marks": [{ "type": "bold" }] },
{ "type": "text", "text": "と" },
{
"type": "text",
"text": "リンク",
"marks": [
{ "type": "link", "attrs": { "href": "https://example.com" } }
]
},
{ "type": "text", "text": "です。" }
]
}
]
}

空の文書は { "type": "doc" } です。

場所 置けるもの
文書(doc)の直下 ブロック(0 個以上)
ブロック paragraph heading bulletList orderedList blockquote codeBlock horizontalRule image table embed
paragraph heading の中 インライン(text hardBreak。0 個以上)
bulletList orderedList の中 listItem(1 個以上)
listItem blockquote の中 ブロック(1 個以上)
codeBlock の中 マークのない text(0 個以上)
table の中 tableRow(1 個以上)
tableRow の中 tableCell か tableHeader(1 個以上)
tableCell tableHeader の中 ブロック(1 個以上)

既定の値の属性は、正規形では省かれます。省いたときは既定の値として扱います。

ノード 属性 型 必須 既定 説明
paragraph textAlign "left" "center" "right" "justify" なし 文字揃え
heading level 1〜6 の整数 ○ 見出しのレベル。正規形でも必ず付く
textAlign paragraph と同じ なし 文字揃え
orderedList start 整数 1 始めの番号
codeBlock language 文字列 なし 言語。HTML では <code class="language-xxx"> になる
image src 空でない文字列 ○ 画像の URL
alt title 文字列 なし 代替テキスト、タイトル
width height 正の整数 なし 幅、高さ(px)
embed src 空でない文字列 ○ 埋め込む URL。HTML では、https のものだけを iframe にする
tableCell tableHeader colspan rowspan 1 以上の整数 1 セルの結合
colwidth 正の整数の配列 なし 列の幅(px)。結合したセルは、列ごとの幅を並べる
text text 空でない文字列 ○ 本文。attrs の中ではなく、ノードのキー
marks マークの配列 なし 下の「マーク」

hardBreak(改行)、horizontalRule(水平線)、bulletList、listItem、blockquote、table、tableRow には、属性はありません。

マーク 属性 説明
link href(必須。空でない文字列)、target(既定 "_blank")、rel(既定 "noopener noreferrer nofollow")、class リンク。HTML では、javascript: などの危ないスキームの href は空になる
bold 太字
code インラインのコード
italic 斜体
strike 取り消し線
underline 下線
customClass class(必須。空でない文字列) 選んだ文字にクラスを付ける(<span class="...">)

表の並び(link → bold → code → italic → strike → underline → customClass)が、HTML での入れ子の順(外側から)で、正規形での marks の並び順です。

書き込んだ値は、次の決まりでそろえてから保存されます。Content API で返る値も、この形です。同じ中身なら同じ JSON になります。

決まり 例
既定の値の属性、null の属性、空の文字列の省ける属性を省く {"start": 1} → 省く、{"textAlign": null} → 省く
属性がなくなったら attrs ごと省く {"type": "paragraph", "attrs": {}} → {"type": "paragraph"}
マークを上の表の順に並べ、同じ種類のマークは最初の 1 つだけ残す [italic, bold] → [bold, italic]
隣り合うテキストのマークが同じなら 1 つにまとめる "太" と "字"(どちらも bold)→ "太字"
空のテキストを省く {"type": "text", "text": ""} → 省く
空の content と空の marks を省く {"type": "paragraph", "content": []} → {"type": "paragraph"}
知らない属性と、ノード・マークの知らないキーを捨てる image の attrs の foo → 捨てる
キーの順を type → attrs → content にする(テキストは type → text → marks)

知らない属性はエラーにせず、捨てます。知らないノードとマークはエラーになります(下の「書き込みのエラー」)。

HTML の文字列を送ると、Hako Rich Text v1 の JSON に変えて保存します。エディタで扱えない要素は、中身だけが残ります。<script> などは捨てられます。HTML ではエラーになりません。

JSON を送ったときに決まりに合わないと、400 が返ります。issues に、フィールドの中の場所(path)と理由(message)が並びます。エラーは、最初の 1 つで止めず、まとめて返ります。

Content API では、次のように返ります。

{
"error": {
"code": "bad_request",
"message": "body.content[0].attrs.level: must be an integer from 1 to 6",
"details": {
"issues": [
{
"path": "body.content[0].attrs.level",
"message": "must be an integer from 1 to 6"
}
]
}
}
}

Admin API では、message と issues が本文のいちばん上に入ります。カスタムフィールドや繰り返しの中では、path は blocks[0].caption.content[0] のようにたどります。

理由(message) 起きるとき
must be a document ({"type": "doc", ...}) 値が type: "doc" のオブジェクトでない(path はフィールド ID だけ)
must be a node with a "type" ノードに type がない
unknown node type "mystery" 知らないノード
"paragraph" is not allowed here (expected inline content (text, hardBreak)) 置けない場所にある
"text" is not allowed here (expected block content) 文書の直下にテキストを置いた
bulletList must contain at least 1 listItem 中身が足りない(「1 個以上」の場所)
must be an array content や marks が配列でない
text must be a string text が文字列でない
must be an integer from 1 to 6 見出しのレベルが 1〜6 でない
must be one of left, center, right, justify 文字揃えの値が違う
is required (a non-empty string) 必須の属性(src href class)がない、または空
must be a string / must be an integer / must be a positive integer 属性の型が違う
unknown mark type "glitter" 知らないマーク
must be a mark with a "type" マークに type がない
  • v1 の中では、ノード、マーク、省ける属性を足すことがあります。足したものは、省いたときに今までと同じ意味になります
  • v1 の中では、今あるノード、マーク、属性の名前と意味、既定の値、置ける場所、正規形の決まりは変えません
  • 形を壊す変更は、新しい形として足し、v1 もしばらく返せるようにします。更新履歴 で知らせます

サイトで描くときは、知らないノードは中身(content)だけを描き、知らないマークと属性は無視するように作っておくと、v1 の中での追加で壊れません。