Merge pull request #817 from alixander/japanese

Scale multi-width unicodes
This commit is contained in:
Alexander Wang 2023-02-14 13:53:36 -08:00 committed by GitHub
commit 53dce56415
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
43 changed files with 9629 additions and 0 deletions

View file

@ -1,5 +1,7 @@
#### Features 🚀
- Many non-Latin languages (e.g. Chinese, Japanese, Korean) are usable now that multi-byte characters are measured correctly. [#817](https://github.com/terrastruct/d2/pull/817)
#### Improvements 🧹
#### Bugfixes ⛑️

View file

@ -38,6 +38,7 @@ func TestE2E(t *testing.T) {
t.Run("regression", testRegression)
t.Run("todo", testTodo)
t.Run("measured", testMeasured)
t.Run("unicode", testUnicode)
}
func testSanity(t *testing.T) {

137
e2etests/testdata/unicode/chinese/dagre/board.exp.json generated vendored Normal file
View file

@ -0,0 +1,137 @@
{
"name": "",
"fontFamily": "SourceSansPro",
"shapes": [
{
"id": "poem",
"type": "text",
"pos": {
"x": 54,
"y": 0
},
"width": 118,
"height": 144,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "transparent",
"stroke": "#0A0F25",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "床前明月光,\n\n疑是地上霜。\n\n举头望明月\n\n低头思故乡。",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "markdown",
"color": "#0A0F25",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 118,
"labelHeight": 144,
"zIndex": 0,
"level": 1
},
{
"id": "a",
"type": "rectangle",
"pos": {
"x": 0,
"y": 244
},
"width": 226,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "所以,即使夏天很热",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 181,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
}
],
"connections": [
{
"id": "(poem -> a)[0]",
"src": "poem",
"srcArrow": "none",
"srcLabel": "",
"dst": "a",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "#0D32B2",
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#676C7E",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 113,
"y": 144
},
{
"x": 113,
"y": 184
},
{
"x": 113,
"y": 204
},
{
"x": 113,
"y": 244
}
],
"isCurve": true,
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
}
]
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 660 KiB

128
e2etests/testdata/unicode/chinese/elk/board.exp.json generated vendored Normal file
View file

@ -0,0 +1,128 @@
{
"name": "",
"fontFamily": "SourceSansPro",
"shapes": [
{
"id": "poem",
"type": "text",
"pos": {
"x": 66,
"y": 12
},
"width": 118,
"height": 144,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "transparent",
"stroke": "#0A0F25",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "床前明月光,\n\n疑是地上霜。\n\n举头望明月\n\n低头思故乡。",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "markdown",
"color": "#0A0F25",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 118,
"labelHeight": 144,
"zIndex": 0,
"level": 1
},
{
"id": "a",
"type": "rectangle",
"pos": {
"x": 12,
"y": 226
},
"width": 226,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "所以,即使夏天很热",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 181,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
}
],
"connections": [
{
"id": "(poem -> a)[0]",
"src": "poem",
"srcArrow": "none",
"srcLabel": "",
"dst": "a",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "#0D32B2",
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#676C7E",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 125,
"y": 156
},
{
"x": 125,
"y": 226
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
}
]
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 660 KiB

179
e2etests/testdata/unicode/emojis/dagre/board.exp.json generated vendored Normal file
View file

@ -0,0 +1,179 @@
{
"name": "",
"fontFamily": "SourceSansPro",
"shapes": [
{
"id": "a",
"type": "rectangle",
"pos": {
"x": 0,
"y": 0
},
"width": 205,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "🙈🙈🙈🙈🙈🙈🙈🙈",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 160,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊",
"type": "rectangle",
"pos": {
"x": 265,
"y": 0
},
"width": 833,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 788,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️",
"type": "rectangle",
"pos": {
"x": 229,
"y": 166
},
"width": 905,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 860,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
}
],
"connections": [
{
"id": "(✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊ -> ☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️)[0]",
"src": "✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊",
"srcArrow": "none",
"srcLabel": "",
"dst": "☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "#0D32B2",
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#676C7E",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 681.5,
"y": 66
},
{
"x": 681.5,
"y": 106
},
{
"x": 681.5,
"y": 126
},
{
"x": 681.5,
"y": 166
}
],
"isCurve": true,
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
}
]
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 326 KiB

170
e2etests/testdata/unicode/emojis/elk/board.exp.json generated vendored Normal file
View file

@ -0,0 +1,170 @@
{
"name": "",
"fontFamily": "SourceSansPro",
"shapes": [
{
"id": "a",
"type": "rectangle",
"pos": {
"x": 12,
"y": 12
},
"width": 205,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "🙈🙈🙈🙈🙈🙈🙈🙈",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 160,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊",
"type": "rectangle",
"pos": {
"x": 237,
"y": 12
},
"width": 833,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 788,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️",
"type": "rectangle",
"pos": {
"x": 201,
"y": 148
},
"width": 905,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 860,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
}
],
"connections": [
{
"id": "(✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊ -> ☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️)[0]",
"src": "✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊✊",
"srcArrow": "none",
"srcLabel": "",
"dst": "☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️☁️",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "#0D32B2",
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#676C7E",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 653.5,
"y": 78
},
{
"x": 653.5,
"y": 148
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
}
]
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 326 KiB

View file

@ -0,0 +1,48 @@
{
"name": "",
"fontFamily": "SourceSansPro",
"shapes": [
{
"id": "a",
"type": "rectangle",
"pos": {
"x": 0,
"y": 0
},
"width": 246,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "ああああああああああ",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 201,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
}
],
"connections": []
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 324 KiB

View file

@ -0,0 +1,48 @@
{
"name": "",
"fontFamily": "SourceSansPro",
"shapes": [
{
"id": "a",
"type": "rectangle",
"pos": {
"x": 12,
"y": 12
},
"width": 246,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "ああああああああああ",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 201,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
}
],
"connections": []
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 324 KiB

View file

@ -0,0 +1,138 @@
{
"name": "",
"fontFamily": "SourceSansPro",
"shapes": [
{
"id": "a",
"type": "rectangle",
"pos": {
"x": 0,
"y": 0
},
"width": 1382,
"height": 98,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "ある日、トマトが道を歩いていたら、道路の向こうからキュウリがやって来ました。\nトマトは驚いて尋ねました。\n「キュウリさん、どうしてあなたはここにいるのですか」 キュウリは答えました。「あなたと同じ理由でここにいます。サラダになるために。」",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 1337,
"labelHeight": 53,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "b",
"type": "rectangle",
"pos": {
"x": 8,
"y": 219
},
"width": 1367,
"height": 115,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "「バナナは皮を剥いて食べるものです。」",
"fontSize": 55,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 1322,
"labelHeight": 70,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
}
],
"connections": [
{
"id": "(a -> b)[0]",
"src": "a",
"srcArrow": "none",
"srcLabel": "",
"dst": "b",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "#0D32B2",
"label": "「バカは死ななきゃ治らない。」",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#676C7E",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 289,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"labelPercentage": 0,
"route": [
{
"x": 691,
"y": 98
},
{
"x": 691,
"y": 146.4
},
{
"x": 691,
"y": 170.7
},
{
"x": 691,
"y": 219.5
}
],
"isCurve": true,
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
}
]
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 469 KiB

View file

@ -0,0 +1,129 @@
{
"name": "",
"fontFamily": "SourceSansPro",
"shapes": [
{
"id": "a",
"type": "rectangle",
"pos": {
"x": 12,
"y": 12
},
"width": 1382,
"height": 98,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "ある日、トマトが道を歩いていたら、道路の向こうからキュウリがやって来ました。\nトマトは驚いて尋ねました。\n「キュウリさん、どうしてあなたはここにいるのですか」 キュウリは答えました。「あなたと同じ理由でここにいます。サラダになるために。」",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 1337,
"labelHeight": 53,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "b",
"type": "rectangle",
"pos": {
"x": 19,
"y": 271
},
"width": 1367,
"height": 115,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "「バナナは皮を剥いて食べるものです。」",
"fontSize": 55,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 1322,
"labelHeight": 70,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
}
],
"connections": [
{
"id": "(a -> b)[0]",
"src": "a",
"srcArrow": "none",
"srcLabel": "",
"dst": "b",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "#0D32B2",
"label": "「バカは死ななきゃ治らない。」",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#676C7E",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 289,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"labelPercentage": 0,
"route": [
{
"x": 703,
"y": 110
},
{
"x": 703,
"y": 271
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
}
]
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 469 KiB

View file

@ -0,0 +1,494 @@
{
"name": "",
"fontFamily": "SourceSansPro",
"shapes": [
{
"id": "a",
"type": "rectangle",
"pos": {
"x": 1646,
"y": 0
},
"width": 668,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "トマトが赤くなったのはなぜですかBecause it saw the salad dressing!👩‍👩‍👧‍👶👩‍👩‍👧‍👶",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 623,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "b",
"type": "rectangle",
"pos": {
"x": 0,
"y": 166
},
"width": 3959,
"height": 171,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "トマトが赤くなったのはなぜですかBecause it saw the salad dressing!👩‍👩‍👧‍👶👩‍👩‍👧‍👶",
"fontSize": 100,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 3914,
"labelHeight": 126,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "c",
"type": "rectangle",
"pos": {
"x": 1817,
"y": 437
},
"width": 326,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "今日はTokyoでsushiを食べました",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 281,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "d",
"type": "rectangle",
"pos": {
"x": 888,
"y": 603
},
"width": 2184,
"height": 100,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "先日、Shibuyaで友達とshoppingを楽😊しんだ後、ramen屋でdelicious😊なラーメンを食べた。",
"fontSize": 43,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 2139,
"labelHeight": 55,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "e",
"type": "rectangle",
"pos": {
"x": 1877,
"y": 803
},
"width": 206,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "English English English",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 161,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "f",
"type": "rectangle",
"pos": {
"x": 1897,
"y": 969
},
"width": 165,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "先日先日先日",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 120,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
}
],
"connections": [
{
"id": "(a -> b)[0]",
"src": "a",
"srcArrow": "none",
"srcLabel": "",
"dst": "b",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "#0D32B2",
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#676C7E",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 1979.5,
"y": 66
},
{
"x": 1979.5,
"y": 106
},
{
"x": 1979.5,
"y": 126
},
{
"x": 1979.5,
"y": 166
}
],
"isCurve": true,
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{
"id": "(b -> c)[0]",
"src": "b",
"srcArrow": "none",
"srcLabel": "",
"dst": "c",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "#0D32B2",
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#676C7E",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 1979.5,
"y": 337
},
{
"x": 1979.5,
"y": 377
},
{
"x": 1979.5,
"y": 397
},
{
"x": 1979.5,
"y": 437
}
],
"isCurve": true,
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{
"id": "(c -> d)[0]",
"src": "c",
"srcArrow": "none",
"srcLabel": "",
"dst": "d",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "#0D32B2",
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#676C7E",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 1979.5,
"y": 503
},
{
"x": 1979.5,
"y": 543
},
{
"x": 1979.5,
"y": 563
},
{
"x": 1979.5,
"y": 603
}
],
"isCurve": true,
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{
"id": "(d -> e)[0]",
"src": "d",
"srcArrow": "none",
"srcLabel": "",
"dst": "e",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "#0D32B2",
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#676C7E",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 1979.5,
"y": 703
},
{
"x": 1979.5,
"y": 743
},
{
"x": 1979.5,
"y": 763
},
{
"x": 1979.5,
"y": 803
}
],
"isCurve": true,
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{
"id": "(e -> f)[0]",
"src": "e",
"srcArrow": "none",
"srcLabel": "",
"dst": "f",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "#0D32B2",
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#676C7E",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 1979.5,
"y": 869
},
{
"x": 1979.5,
"y": 909
},
{
"x": 1979.5,
"y": 929
},
{
"x": 1979.5,
"y": 969
}
],
"isCurve": true,
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
}
]
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 328 KiB

View file

@ -0,0 +1,449 @@
{
"name": "",
"fontFamily": "SourceSansPro",
"shapes": [
{
"id": "a",
"type": "rectangle",
"pos": {
"x": 1657,
"y": 12
},
"width": 668,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "トマトが赤くなったのはなぜですかBecause it saw the salad dressing!👩‍👩‍👧‍👶👩‍👩‍👧‍👶",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 623,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "b",
"type": "rectangle",
"pos": {
"x": 12,
"y": 148
},
"width": 3959,
"height": 171,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "トマトが赤くなったのはなぜですかBecause it saw the salad dressing!👩‍👩‍👧‍👶👩‍👩‍👧‍👶",
"fontSize": 100,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 3914,
"labelHeight": 126,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "c",
"type": "rectangle",
"pos": {
"x": 1828,
"y": 389
},
"width": 326,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "今日はTokyoでsushiを食べました",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 281,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "d",
"type": "rectangle",
"pos": {
"x": 899,
"y": 525
},
"width": 2184,
"height": 100,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "先日、Shibuyaで友達とshoppingを楽😊しんだ後、ramen屋でdelicious😊なラーメンを食べた。",
"fontSize": 43,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 2139,
"labelHeight": 55,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "e",
"type": "rectangle",
"pos": {
"x": 1888,
"y": 695
},
"width": 206,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "English English English",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 161,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "f",
"type": "rectangle",
"pos": {
"x": 1909,
"y": 831
},
"width": 165,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "先日先日先日",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 120,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
}
],
"connections": [
{
"id": "(a -> b)[0]",
"src": "a",
"srcArrow": "none",
"srcLabel": "",
"dst": "b",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "#0D32B2",
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#676C7E",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 1991.5,
"y": 78
},
{
"x": 1991.5,
"y": 148
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{
"id": "(b -> c)[0]",
"src": "b",
"srcArrow": "none",
"srcLabel": "",
"dst": "c",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "#0D32B2",
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#676C7E",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 1991.5,
"y": 319
},
{
"x": 1991.5,
"y": 389
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{
"id": "(c -> d)[0]",
"src": "c",
"srcArrow": "none",
"srcLabel": "",
"dst": "d",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "#0D32B2",
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#676C7E",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 1991.5,
"y": 455
},
{
"x": 1991.5,
"y": 525
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{
"id": "(d -> e)[0]",
"src": "d",
"srcArrow": "none",
"srcLabel": "",
"dst": "e",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "#0D32B2",
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#676C7E",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 1991.5,
"y": 625
},
{
"x": 1991.5,
"y": 695
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{
"id": "(e -> f)[0]",
"src": "e",
"srcArrow": "none",
"srcLabel": "",
"dst": "f",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "#0D32B2",
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#676C7E",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 1991.5,
"y": 761
},
{
"x": 1991.5,
"y": 831
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
}
]
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 327 KiB

48
e2etests/testdata/unicode/korean/dagre/board.exp.json generated vendored Normal file
View file

@ -0,0 +1,48 @@
{
"name": "",
"fontFamily": "SourceSansPro",
"shapes": [
{
"id": "a",
"type": "rectangle",
"pos": {
"x": 0,
"y": 0
},
"width": 205,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "고생끝에낙이온다",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 160,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
}
],
"connections": []
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 324 KiB

48
e2etests/testdata/unicode/korean/elk/board.exp.json generated vendored Normal file
View file

@ -0,0 +1,48 @@
{
"name": "",
"fontFamily": "SourceSansPro",
"shapes": [
{
"id": "a",
"type": "rectangle",
"pos": {
"x": 12,
"y": 12
},
"width": 205,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "고생끝에낙이온다",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 160,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
}
],
"connections": []
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 324 KiB

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 334 KiB

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 333 KiB

View file

@ -0,0 +1,226 @@
{
"name": "",
"fontFamily": "SourceSansPro",
"shapes": [
{
"id": "a",
"type": "rectangle",
"pos": {
"x": 275,
"y": 0
},
"width": 428,
"height": 98,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "有一个叫做夏天的季节。\n ある季節、夏という名前がついています。\n한 계절, 여름이란 이름이 있습니다.",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 383,
"labelHeight": 53,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "b",
"type": "rectangle",
"pos": {
"x": 0,
"y": 198
},
"width": 448,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "夏天的时候,天气非常热,人们总是流着汗。",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 403,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "c",
"type": "text",
"pos": {
"x": 508,
"y": 199
},
"width": 492,
"height": 64,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "transparent",
"stroke": "#0A0F25",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "夏になると、とても暑くて、人々は汗を流しています。\n\n여름에는 매우 더워서 사람들은 땀을 흘립니다.",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "markdown",
"color": "#0A0F25",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 492,
"labelHeight": 64,
"zIndex": 0,
"level": 1
}
],
"connections": [
{
"id": "(a -> b)[0]",
"src": "a",
"srcArrow": "none",
"srcLabel": "",
"dst": "b",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "#0D32B2",
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#676C7E",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 357.83838383838383,
"y": 98
},
{
"x": 250.76767676767676,
"y": 138
},
{
"x": 224,
"y": 158
},
{
"x": 224,
"y": 198
}
],
"isCurve": true,
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{
"id": "(a -> c)[0]",
"src": "a",
"srcArrow": "none",
"srcLabel": "",
"dst": "c",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "#0D32B2",
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#676C7E",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 620.1616161616162,
"y": 98
},
{
"x": 727.2323232323232,
"y": 138
},
{
"x": 754,
"y": 158.2
},
{
"x": 754,
"y": 199
}
],
"isCurve": true,
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
}
]
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 661 KiB

View file

@ -0,0 +1,216 @@
{
"name": "",
"fontFamily": "SourceSansPro",
"shapes": [
{
"id": "a",
"type": "rectangle",
"pos": {
"x": 93,
"y": 12
},
"width": 428,
"height": 98,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "有一个叫做夏天的季节。\n ある季節、夏という名前がついています。\n한 계절, 여름이란 이름이 있습니다.",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 383,
"labelHeight": 53,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "b",
"type": "rectangle",
"pos": {
"x": 12,
"y": 190
},
"width": 448,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "夏天的时候,天气非常热,人们总是流着汗。",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 403,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "c",
"type": "text",
"pos": {
"x": 480,
"y": 190
},
"width": 492,
"height": 64,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "transparent",
"stroke": "#0A0F25",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": false,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "夏になると、とても暑くて、人々は汗を流しています。\n\n여름에는 매우 더워서 사람들은 땀을 흘립니다.",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "markdown",
"color": "#0A0F25",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 492,
"labelHeight": 64,
"zIndex": 0,
"level": 1
}
],
"connections": [
{
"id": "(a -> b)[0]",
"src": "a",
"srcArrow": "none",
"srcLabel": "",
"dst": "b",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "#0D32B2",
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#676C7E",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 236,
"y": 110
},
{
"x": 236,
"y": 190
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
},
{
"id": "(a -> c)[0]",
"src": "a",
"srcArrow": "none",
"srcLabel": "",
"dst": "c",
"dstArrow": "triangle",
"dstLabel": "",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "#0D32B2",
"label": "",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#676C7E",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 0,
"labelHeight": 0,
"labelPosition": "",
"labelPercentage": 0,
"route": [
{
"x": 378.66666666666663,
"y": 110
},
{
"x": 378.66666666666663,
"y": 150
},
{
"x": 726,
"y": 150
},
{
"x": 726,
"y": 190
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 0
}
]
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 661 KiB

View file

@ -0,0 +1,48 @@
{
"name": "",
"fontFamily": "SourceSansPro",
"shapes": [
{
"id": "おやすみなさい",
"type": "rectangle",
"pos": {
"x": 0,
"y": 0
},
"width": 185,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 15,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": true,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "おやすみなさい",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 140,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
}
],
"connections": []
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 324 KiB

View file

@ -0,0 +1,48 @@
{
"name": "",
"fontFamily": "SourceSansPro",
"shapes": [
{
"id": "おやすみなさい",
"type": "rectangle",
"pos": {
"x": 12,
"y": 12
},
"width": 185,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 15,
"borderRadius": 0,
"fill": "#F7F8FE",
"stroke": "#0D32B2",
"shadow": false,
"3d": false,
"multiple": false,
"double-border": true,
"tooltip": "",
"link": "",
"icon": null,
"iconPosition": "",
"blend": false,
"fields": null,
"methods": null,
"columns": null,
"label": "おやすみなさい",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "#0A0F25",
"italic": false,
"bold": true,
"underline": false,
"labelWidth": 140,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
}
],
"connections": []
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 324 KiB

139
e2etests/unicode_test.go Normal file
View file

@ -0,0 +1,139 @@
package e2etests
import (
_ "embed"
"testing"
)
func testUnicode(t *testing.T) {
tcs := []testCase{
{
name: "japanese-basic",
script: `a: ああああああああああ
`,
},
{
name: "japanese-full",
script: `a: "ある日、トマトが道を歩いていたら、道路の向こうからキュウリがやって来ました。\nトマトは驚いて尋ねました。\n「キュウリさん、どうしてあなたはここにいるのですか」 キュウリは答えました。「あなたと同じ理由でここにいます。サラダになるために。」"
b: "「バナナは皮を剥いて食べるものです。」" {
style.font-size: 55
}
a -> b: バカは死ななきゃ治らない
`,
},
{
name: "emojis",
script: `a: 🙈🙈🙈🙈🙈🙈🙈🙈
->
`,
},
{
name: "with-style",
script: `おやすみなさい: {style.stroke-width: 15; style.double-border: true}
`,
},
{
name: "japanese-mixed",
script: `a: "トマトが赤くなったのはなぜですかBecause it saw the salad dressing!👩‍👩‍👧‍👶👩‍👩‍👧‍👶"
b: "トマトが赤くなったのはなぜですかBecause it saw the salad dressing!👩‍👩‍👧‍👶👩‍👩‍👧‍👶" {
style.font-size: 100
}
c: 今日はTokyoでsushiを食べました
d: 先日Shibuyaで友達とshoppingを楽😊しんだ後ramen屋でdelicious😊なラーメンを食べた{
style.font-size: 43
}
e: English English English
f: 先日先日先日
a -> b -> c -> d -> e -> f
`,
},
{
name: "chinese",
script: `poem: |md
床前明月光
疑是地上霜
举头望明月
低头思故乡
|
a: 所以即使夏天很热
poem -> a
`,
},
{
name: "korean",
script: `a: 고생끝에낙이온다
`,
},
{
name: "mixed-language",
script: `a: 有一个叫做夏天的季节\n ある季節夏という名前がついています\n한 계절, 여름이란 이름이 있습니다.
b: 夏天的时候天气非常热人们总是流着汗
c: |md
夏になるととても暑くて人々は汗を流しています
여름에는 매우 더워서 사람들은 땀을 흘립니다.
|
a -> b
a -> c
`,
},
{
name: "mixed-language-2",
script: `a: () - Mandarin Chinese
b: ສະບາຍດີ (sabaai dii) - Lao
c: ជំរបសួរ (jomreab suor) - Khmer
d: สวัสดี (-wàt-dii) - Thai
e: ສະບາຍດີ (sabaidee) - Lao
f: ဟယ်လို (helaou) - Burmese
g: mari (まり) - Ainu
h: cào () - Zhuang
i: күнтізбе (kúntízbe) - Kazakh
j: բարև (barev) - Armenian
k: монгол (mongol) - Mongolian
l: mila (میلا) - Uyghur
m: નમસ્તે (namaste) - Gujarati
n: 漢字 (kanji) - Japanese
o: (wi) - Korean
p: 吾哥 (ngǔgāi) - Cantonese
a -> b -> c -> d
e -> f -> g -> h
i -> j -> k -> l
m -> n -> o -> p
မင်္ဂလ (mingalaba) - Burmese
сайн уу (sain uu) - Mongolian
ਸਤਿ ਸ੍ਰ ਅਕ (sat sri akal) - Punjabi
你吃了吗 ( chī le ma) - Mandarin Chinese
(fan) - Zhuang
مەن سىزنى ياخشى ئۈمىد ق
`,
},
}
runa(t, tcs)
}

1
go.mod generated
View file

@ -12,6 +12,7 @@ require (
github.com/lucasb-eyer/go-colorful v1.2.0
github.com/mazznoer/csscolorparser v0.1.3
github.com/playwright-community/playwright-go v0.2000.1
github.com/rivo/uniseg v0.4.3
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.8.1
github.com/yuin/goldmark v1.5.3

2
go.sum generated
View file

@ -128,6 +128,8 @@ github.com/playwright-community/playwright-go v0.2000.1/go.mod h1:1y9cM9b9dVHnuR
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw=
github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=

View file

@ -257,6 +257,8 @@ func (ruler *Ruler) measureNode(depth int, n *html.Node, fontFamily *d2fonts.Fon
if isCode {
w *= FontSize_pre_code_em
h *= FontSize_pre_code_em
} else {
w = ruler.scaleUnicode(w, font, str)
}
if debugMeasure {
fmt.Printf("%stext(%v,%v)\n", depthStr, w, h)

View file

@ -5,10 +5,12 @@ package textmeasure
import (
"math"
"strings"
"unicode"
"unicode/utf8"
"github.com/golang/freetype/truetype"
"github.com/rivo/uniseg"
"oss.terrastruct.com/d2/d2renderers/d2fonts"
"oss.terrastruct.com/d2/lib/geo"
@ -164,8 +166,52 @@ func (r *Ruler) addFontSize(font d2fonts.Font) {
r.tabWidths[font] = atlas.glyph(' ').advance * TAB_SIZE
}
func (t *Ruler) scaleUnicode(w float64, font d2fonts.Font, s string) float64 {
// Weird unicode stuff is going on when this is true
// See https://github.com/rivo/uniseg#grapheme-clusters
// This method is a good-enough approximation. It overshoots, but not by much.
// I suspect we need to import a font with the right glyphs to get the precise measurements
// but Hans fonts are heavy.
if uniseg.GraphemeClusterCount(s) != len(s) {
for _, line := range strings.Split(s, "\n") {
lineW, _ := t.MeasurePrecise(font, line)
gr := uniseg.NewGraphemes(line)
mono := d2fonts.SourceCodePro.Font(font.Size, font.Style)
for gr.Next() {
if gr.Width() == 1 {
continue
}
// For each grapheme which doesn't have width=1, the ruler measured wrongly.
// So, replace the measured width with a scaled measurement of a monospace version
var prevRune rune
dot := t.Orig.Copy()
b := newRect()
for _, r := range gr.Runes() {
var control bool
dot, control = t.controlRune(r, dot, font)
if control {
continue
}
var bounds *rect
_, _, bounds, dot = t.atlases[font].DrawRune(prevRune, r, dot)
b = b.union(bounds)
prevRune = r
}
lineW -= b.w()
lineW += t.spaceWidth(mono) * float64(gr.Width())
}
w = math.Max(w, lineW)
}
}
return w
}
func (t *Ruler) Measure(font d2fonts.Font, s string) (width, height int) {
w, h := t.MeasurePrecise(font, s)
w = t.scaleUnicode(w, font, s)
return int(math.Ceil(w)), int(math.Ceil(h))
}