新しいレイアウトファイルのスキーマ #4

Closed
hidakatsuya opened this Issue Aug 4, 2015 · 9 comments

Comments

Projects
None yet
2 participants
@hidakatsuya
Member

hidakatsuya commented Aug 4, 2015


これは v0.9.0 における 機能の実装コンセプト であり、この内容を基にユーザからのフィードバックを得てよりよい仕様を議論し、導き出すことが目的。 コメント欄での議論により、内容は適宜更新される。また、技術的な制約など、実際の機能が必ずしもコンセプト通りになるとは限らない。


モチベーション

現状

現在のレイアウトファイルには下記のようなデータ構造でレイアウト情報が記録されている:

{
  "version":           "0.0.0",
  "config": {
    "title":           "Report Title",
    "page": {
      "paper-type":    "A4",
      "width":         0.0,
      "height":        0.0,
      "orientation":   "landscape",
      "margin-top":    0.0,
      "margin-bottom": 0.0,
      "margin-left":   0.0,
      "margin-right":  0.0,
    }
  },
  "svg": "<svg><g class=\"canvas\">...</g></svg>",
  "state": {
    "layout-guide": [{ "type": "x", "position": 0.0 },,,],
  }
}
:
"svg": {
  "<svg>
     <g class=\"canvas\">
       <!--LAYOUT<rect x-id=\"rect_id\" x=\"100.0\" y=\"100.0\" width=\"200\" height=\"200\"/>-->
       <!--SHAPE{ "type": "s-text", "id": "rect_id", "display": "true", "svg": { "attrs": {...} }}SHAPE-->
     </g>
   </svg>"
}
:
  • 図形の情報を SVG としてそのまま記録
  • これに加えて、Generator 用に各図形の情報を JSON 化して記録
  • 上記を区別するために、それぞれ <!--LYAOUT ... LAYOUT--> <!--SHAPE ... SHAPE--> で括る

図形の情報を SVG そのままに記録しているのは、Editor でレイアウトを開く際に簡単に復元できるようにするためだが、 Generator で各図形の情報を読み取りやすくするため、レイアウト保存時に各図形の情報を JSON として付与する形で記録している。

現在のレイアウトファイル .tlf 内の仕様は Spec: Layout FileSpec: SVG and Shapes で公開している。

問題点

  • 機能の改善などの歴史的経緯や互換性維持のために、SVG に冗長な属性が含まれていたり、無駄な情報が混在しており Editor/Generator の実装を複雑なものにしている
  • 各図形の情報を表現する JSON 構造に SVG の属性値とそれ以外の属性値が混在しており、構造があいまいで非常に扱いにくく、かつ分かりにくい
例: テキストオブジェクトの JSON スキーマ
{
  "type": "s-text",
  "id": "text_id",
  "display": "true",
  "line-height": 20.0,
  "line-height-ratio": 2.5,
  "valign": "top",
  "box": {
    "x": 100.0,
    "y": 100.0,
    "width": 100.0,
    "height": 100.0
  },
  "text": ["line1", "line2"],
  "svg": {
    "attrs": {
      "text-anchor": "start",
      "font-family": "Helvetica",
      "font-size": "18",
      "character-spacing": "3.0",
         :
    }
  }
}
  • SVG (テンプレート) に強く依存していることで、Editor の実装もテンプレートとロジックが強く結合し、コードの見通しが非常に悪い
  • 同様に、今後、コンポーネント志向でのリファクタリングあるいは書き直しをする上での障壁になる
  • サードパーティソフトウェアなど外部のツールがレイアウト情報を活用したり連携することが困難
  • Diff が非常に取りづらい

Schema の刷新

方針

  • 全ての情報を JSON で記録
  • SVG の構造や属性の内包、SVG との依存を完全に排除
  • 各オブジェクト(図形)の JSON スキーマも一新し、統一された理解しやすい構造へ改善
  • Minify ではなく Pretty 形式で保存し、人間にも理解しやすく Diff も取りやすくする

互換性について

Thinreports のバージョン 新しいスキーマ(Editor v0.9 以降で作成)の読み込み 古いスキーマ(Editor v0.9 未満で作成)の読み込み
0.9 未満 x o
0.9, 1.0 o o
1.1 以上 o x

レイアウトファイルの新しいスキーマ

メインスキーマ

{
  "version": "0.0.0",
  "title": "Report Title",
  "report": {
    "paper-type": "A4",
    "width": 0.0,
    "height": 0.0,
    "orientation": "landscape",
    "margin": [0.0, 0.0, 0.0, 0.0]
  },
  "state": {
    "layout-guides": [
      { "type": "x", "position": 0.0 }
    ]
  },
  "items": [
    { "type": "rect", "id": "", "x": 0.0, "y": 0.0, "width": 0.0, "height": 0.0, "style": { "stroke-width": 1 }},
    { "type": "text-block", "id": "price", "x": 0.0, "y": 0.0, },
    { },
  ]
}
  • "items":[] には、レイヤー順(降順)で各オブジェクト(図形)の JSON 情報を順番に記録
  • 不要なネスト構造を排除し、極力見やすい構造へ

オブジェクト(図形)スキーマ

概要

  • スタイルの情報は全て style 内に記録
  • プロパティの省略は許可しない。必ずスキーマにあるプロパティを持つ

Rect

{
  "id": "",
  "type": "rect",
  "x": 0.0,
  "y": 0.0,
  "width": 0.0,
  "height": 0.0,
  "rx": 0.0,
  "ry": 0.0,
  "description": "Description for shape",
  "display": true,
  "style": {
    "border-width": 1,
    "border-color": "#000000",
    "border-style": "dashed",
    "fill-color": "#ffffff"
  }
}

Ellipse

{
  "id": "",
  "type": "ellipse",
  "cx": 0.0,
  "cy": 0.0,
  "rx": 0.0,
  "ry": 0.0,
  "description": "Description for shape",
  "display": true,
  "style": {
    "border-width": 1,
    "border-color": "#000000",
    "border-style": "dashed",
    "fill-color": "#ffffff"
  }
}

Line

{
  "id": "",
  "type": "line",
  "x1": 0.0,
  "y2": 0.0,
  "x2": 0.0,
  "y2": 0.0,
  "description": "Description for shape",
  "display": true,
  "style": {
    "border-width": 1,
    "border-color": "#000000",
    "border-style": "dashed",
  }
}

Text

{
  "id": "",
  "type": "text",
  "x": 0.0,
  "y": 0.0,
  "width": 0.0,
  "height": 0.0,
  "description": "Description for shape",
  "display": true,
  "texts": [
    "text line 1st",
    "text line 2nd"
  ],
  "style": {
    "font-family": ["Helvetica"],
    "font-size": 18,
    "color": "#000000",
    "font-style": [ "bold", "italic", "linethrough", "underline" ],
    "text-align": "left",
    "vertical-align": "top",
    "line-height": 30,
    "line-height-ratio": 1.5,
    "letter-spacing": "normal"
  }
}

Image

{
  "id": "",
  "type": "image",
  "x": 0.0,
  "y": 0.0,
  "width": 0.0,
  "height": 0.0,
  "description": "Description for shape",
  "data": {
    "mime-type": "image/png",
    "base64": "AAAAAAAAAAAAAAA..."
  },
  "display": true
}

Text block

{
  "id": "text_block_id",
  "reference-id": "",
  "type": "text-block",
  "x": 0.0,
  "y": 0.0,
  "width": 0.0,
  "height": 0.0,
  "description": "Description for shape",
  "value": "default value",
  "mulitple-line": true,
  "format": {
    "base": "Created at {value}",
    "type": "datetime",
    "datetime": {
      "format": "%Y-%m-%d %H:%M:%S"
    }
  },
  "display": true,
  "style": {
    "font-family": ["Helvetica"],
    "font-size": 18,
    "color": "#000000",
    "font-style": [ "bold", "italic", "linethrough", "underline" ],
    "text-align": "left",
    "vertical-align": "top",
    "line-height": 30,
    "line-height-ratio": 1.5,
    "letter-spacing": "normal",
    "overflow": "truncate",
    "word-wrap": "break-word"
  }
}

数値書式:

{
  "format": {
    "number": {
      "delimiter": ",",
      "precision": 3
    }
  }
}

字詰め書式:

{
  "format": {
    "padding": {
      "length":  5,
      "char": "0",
      "direction": "L"
    }
  }
}

Image block

{
  "id": "image_block_id",
  "type": "image-block",
  "x": 0.0,
  "y": 0.0,
  "width": 0.0,
  "height": 0.0,
  "description": "Description for shape",
  "display": true,
  "style": {
    "position-x": "left",
    "position-y": "top"
  }
}

Page number

{
  "id": "",
  "type": "page-number",
  "x": 0.0,
  "y": 0.0,
  "width": 0.0,
  "height": 0.0,
  "description": "Description for shape",
  "format": "{page} / {total}",
  "target": "report",
  "display": true,
  "style": {
    "font-family": ["Helvetica"],
    "font-size": 18,
    "color": "#000000",
    "font-style": [ "bold", "italic", "linethrough", "underline" ],
    "text-align": "left",
    "line-height": 30.0,
    "line-height-ratio": 1.5,
    "letter-spacing": "normal",
    "overflow": "truncate"
  }
}

List

{
  "id": "default",
  "type": "list",
  "x": 100.0,
  "y": 100.0,
  "width": 200.0,
  "height": 300.0,
  "description": "Description for shape",
  "content-height": 190.0,
  "auto-page-break": true,
  "display": true,
  "header": {
    "enabled": true,
    "height": 10.0,
    "translate": { "x": 100.0, "y": 100.0 },
    "items": [
      { "type": "rect", "id": "" },
      { "type": "text", "id": "" }
    ]
  },
  "detail": {
    "height": 10.0,
    "translate": { "x": 100.0, "y": 100.0 },
    "items": [
      { "type": "rect", "id": "" },
      { "type": "text", "id": "" }
    ]
  },
  "page-footer": {
    "enabled": true,
    "height": 10.0,
    "translate": { "x": 100.0, "y": 100.0 },
    "items": [
      { "type": "rect", "id": "" },
      { "type": "text", "id": "" }
    ]
  },
  "footer": {
    "enabled": true,
    "height": 10.0,
    "translate": { "x": 100.0, "y": 100.0 },
    "items": [
      { "type": "rect", "id": "" },
      { "type": "text", "id": "" }
    ]
  }
}
  • 各セクションの "items: []" には、オブジェクト(図形)の JSON スキーマをレイヤー降順で格納

@hidakatsuya hidakatsuya added the CONCEPT label Aug 4, 2015

@hidakatsuya hidakatsuya added this to the Concepts of 1.0.0 milestone Aug 4, 2015

@hidakatsuya hidakatsuya referenced this issue in thinreports/thinreports-editor Aug 4, 2015

Closed

New schema of layout-file (.tlf) #53

@maeda-m maeda-m referenced this issue in thinreports/thinreports-editor Aug 24, 2015

Merged

New format for layout file #56

4 of 4 tasks complete

@maeda-m maeda-m added CONCEPT_FROZEN and removed CONCEPT labels Aug 24, 2015

@maeda-m

This comment has been minimized.

Show comment
Hide comment
@maeda-m

maeda-m Aug 24, 2015

Member

This concept was frozen, I have started to develop.
thinreports/thinreports-editor#56

Member

maeda-m commented Aug 24, 2015

This concept was frozen, I have started to develop.
thinreports/thinreports-editor#56

@maeda-m maeda-m closed this Aug 24, 2015

@maeda-m maeda-m reopened this Aug 24, 2015

@hidakatsuya hidakatsuya added the CONCEPT label Aug 24, 2015

@hidakatsuya

This comment has been minimized.

Show comment
Hide comment
@hidakatsuya

hidakatsuya Sep 7, 2015

Member

@maeda-m

Image の data ですが、以下のようにデータと MIME-Type を分けて持ちたいと思いますがどうでしょう?理由は、まず base64 データを抜き出す必要がないのと、同じように画像タイプを知ることも簡単になるからです。また、キー名を base64-data などにすることができるので、原案の data よりもその値が Base64 データということが明確になります。

{
  "id": "",
  "type": "image",
  "x": 0.0,
  "y": 0.0,
  "width": 0.0,
  "height": 0.0,
  "description": "Description for shape",
  "base64-data": "AAAAAAAAAAAAAAA",
  "mime-type": "image/png",
  "style": {
    "display": true
  }
}
Member

hidakatsuya commented Sep 7, 2015

@maeda-m

Image の data ですが、以下のようにデータと MIME-Type を分けて持ちたいと思いますがどうでしょう?理由は、まず base64 データを抜き出す必要がないのと、同じように画像タイプを知ることも簡単になるからです。また、キー名を base64-data などにすることができるので、原案の data よりもその値が Base64 データということが明確になります。

{
  "id": "",
  "type": "image",
  "x": 0.0,
  "y": 0.0,
  "width": 0.0,
  "height": 0.0,
  "description": "Description for shape",
  "base64-data": "AAAAAAAAAAAAAAA",
  "mime-type": "image/png",
  "style": {
    "display": true
  }
}
@maeda-m

This comment has been minimized.

Show comment
Hide comment
@maeda-m

maeda-m Sep 7, 2015

Member

@hidakatsuya

「MIME-Typeを分けて持ちたい」というのはOKだと思います。
気になるのはSchemaの構造ですが、 data URI scheme の構成を分解した構造にすると良いかなと思います。

{
  "id": "",
  "type": "image",
  "x": 0.0,
  "y": 0.0,
  "width": 0.0,
  "height": 0.0,
  "description": "Description for shape",
  "data": {
    "mime-type": "image/png",
    "base64": "AAAAAAAAAAAAAAA"
  },
  "style": {
    "display": true
  }
}
Member

maeda-m commented Sep 7, 2015

@hidakatsuya

「MIME-Typeを分けて持ちたい」というのはOKだと思います。
気になるのはSchemaの構造ですが、 data URI scheme の構成を分解した構造にすると良いかなと思います。

{
  "id": "",
  "type": "image",
  "x": 0.0,
  "y": 0.0,
  "width": 0.0,
  "height": 0.0,
  "description": "Description for shape",
  "data": {
    "mime-type": "image/png",
    "base64": "AAAAAAAAAAAAAAA"
  },
  "style": {
    "display": true
  }
}
@hidakatsuya

This comment has been minimized.

Show comment
Hide comment
@hidakatsuya

hidakatsuya Sep 7, 2015

Member

気になるのはSchemaの構造ですが、 data URI scheme の構成を分解した構造にすると良いかなと思います。

良いですね。FROZEN_CONCEPT ですが、そうしましょう。後ほど修正しておきます。

Member

hidakatsuya commented Sep 7, 2015

気になるのはSchemaの構造ですが、 data URI scheme の構成を分解した構造にすると良いかなと思います。

良いですね。FROZEN_CONCEPT ですが、そうしましょう。後ほど修正しておきます。

@hidakatsuya

This comment has been minimized.

Show comment
Hide comment
@hidakatsuya

hidakatsuya Sep 7, 2015

Member

下記の通り、Image スキーマの data 配下に base64mime-type を置き、それぞれ Base64 データと画像の MIME-Type を定義するよう変更しました。

before:

{
  "data": "image/png;base64,AAAAAAAA..."
}

after:

{
  "data": {
    "mime-type": "image/png",
    "base64": "AAAAAAAAA..."
  }
}
Member

hidakatsuya commented Sep 7, 2015

下記の通り、Image スキーマの data 配下に base64mime-type を置き、それぞれ Base64 データと画像の MIME-Type を定義するよう変更しました。

before:

{
  "data": "image/png;base64,AAAAAAAA..."
}

after:

{
  "data": {
    "mime-type": "image/png",
    "base64": "AAAAAAAAA..."
  }
}

@hidakatsuya hidakatsuya referenced this issue in thinreports/thinreports-generator Sep 7, 2015

Merged

New format for layout file and deprecate old format #35

3 of 3 tasks complete
@hidakatsuya

This comment has been minimized.

Show comment
Hide comment
@hidakatsuya

hidakatsuya Sep 26, 2015

Member

FROZEN_CONCEPT なのに 2度目の仕様変更になりますが Pretty フォーマットな JSON スキーマで出力する仕様を追加しました。

Member

hidakatsuya commented Sep 26, 2015

FROZEN_CONCEPT なのに 2度目の仕様変更になりますが Pretty フォーマットな JSON スキーマで出力する仕様を追加しました。

@hidakatsuya hidakatsuya modified the milestones: 1.0.0, 0.9.0 Feb 21, 2016

@hidakatsuya

This comment has been minimized.

Show comment
Hide comment
@hidakatsuya

hidakatsuya Apr 10, 2016

Member

layout-guidelayout-guides に修正しました。

Member

hidakatsuya commented Apr 10, 2016

layout-guidelayout-guides に修正しました。

@hidakatsuya

This comment has been minimized.

Show comment
Hide comment
@hidakatsuya

hidakatsuya Apr 10, 2016

Member

displaystyle の中ではなく外(top-level)で定義することにしました。

Member

hidakatsuya commented Apr 10, 2016

displaystyle の中ではなく外(top-level)で定義することにしました。

@hidakatsuya

This comment has been minimized.

Show comment
Hide comment
@hidakatsuya

hidakatsuya Apr 11, 2016

Member

objectsitems へ変更しました。

Member

hidakatsuya commented Apr 11, 2016

objectsitems へ変更しました。

@hidakatsuya hidakatsuya referenced this issue in thinreports-php/thinreports-php Jan 8, 2018

Open

Support v0.9(new) format schema #23

@hidakatsuya hidakatsuya closed this May 8, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment