@amaster.ai/pi-lark 0.1.7 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/skills/lark-apps/SKILL.md +39 -6
- package/skills/lark-apps/references/lark-apps-cloud-dev.md +5 -4
- package/skills/lark-apps/references/lark-apps-create.md +6 -3
- package/skills/lark-apps/references/lark-apps-get.md +1 -1
- package/skills/lark-apps/references/lark-apps-list.md +1 -1
- package/skills/lark-apps/references/lark-apps-local-dev.md +27 -1
- package/skills/lark-apps/references/lark-apps-release-create.md +1 -1
- package/skills/lark-base/SKILL.md +14 -6
- package/skills/lark-base/references/lark-base-dashboard-block-get-data.md +17 -1
- package/skills/lark-base/references/lark-base-dashboard.md +17 -4
- package/skills/lark-base/references/lark-base-data-query-guide.md +8 -0
- package/skills/lark-base/references/lark-base-field-create.md +19 -8
- package/skills/lark-base/references/lark-base-field-json.md +5 -2
- package/skills/lark-calendar/SKILL.md +1 -1
- package/skills/lark-doc/SKILL.md +26 -61
- package/skills/lark-doc/references/genres/business-analysis.md +30 -0
- package/skills/lark-doc/references/genres/data-report.md +32 -0
- package/skills/lark-doc/references/genres/email.md +38 -0
- package/skills/lark-doc/references/genres/execution-plan.md +27 -0
- package/skills/lark-doc/references/genres/formal-doc.md +37 -0
- package/skills/lark-doc/references/genres/meeting-minutes.md +24 -0
- package/skills/lark-doc/references/genres/memo-brief.md +25 -0
- package/skills/lark-doc/references/genres/official-redhead.md +73 -0
- package/skills/lark-doc/references/genres/prd.md +26 -0
- package/skills/lark-doc/references/genres/proposal.md +24 -0
- package/skills/lark-doc/references/genres/research-report.md +32 -0
- package/skills/lark-doc/references/genres/retrospective.md +25 -0
- package/skills/lark-doc/references/genres/route-consumer.md +37 -0
- package/skills/lark-doc/references/genres/route-creative.md +36 -0
- package/skills/lark-doc/references/genres/route-knowledge.md +39 -0
- package/skills/lark-doc/references/genres/route-marketing.md +40 -0
- package/skills/lark-doc/references/genres/route-media.md +36 -0
- package/skills/lark-doc/references/genres/route-opinion.md +38 -0
- package/skills/lark-doc/references/genres/route-personal-brand.md +36 -0
- package/skills/lark-doc/references/genres/route-platform.md +9 -0
- package/skills/lark-doc/references/genres/route-report.md +10 -0
- package/skills/lark-doc/references/genres/route-workplace.md +17 -0
- package/skills/lark-doc/references/genres/sop-tutorial.md +41 -0
- package/skills/lark-doc/references/genres/technical-doc.md +39 -0
- package/skills/lark-doc/references/genres/wechat.md +39 -0
- package/skills/lark-doc/references/genres/weekly-report.md +24 -0
- package/skills/lark-doc/references/genres/white-paper.md +32 -0
- package/skills/lark-doc/references/genres/xiaohongshu.md +38 -0
- package/skills/lark-doc/references/lark-doc-create-workflow.md +121 -0
- package/skills/lark-doc/references/lark-doc-create.md +22 -48
- package/skills/lark-doc/references/lark-doc-fetch.md +75 -92
- package/skills/lark-doc/references/lark-doc-history.md +16 -15
- package/skills/lark-doc/references/lark-doc-md.md +5 -1
- package/skills/lark-doc/references/lark-doc-media-download.md +2 -1
- package/skills/lark-doc/references/lark-doc-script.md +76 -0
- package/skills/lark-doc/references/lark-doc-update.md +70 -222
- package/skills/lark-doc/references/lark-doc-whiteboard.md +5 -9
- package/skills/lark-doc/references/lark-doc-xml-extended-blocks.md +17 -12
- package/skills/lark-doc/references/lark-doc-xml.md +38 -167
- package/skills/lark-drive/SKILL.md +7 -5
- package/skills/lark-drive/references/lark-drive-apply-permission.md +1 -1
- package/skills/lark-drive/references/lark-drive-copy.md +87 -0
- package/skills/lark-drive/references/lark-drive-download.md +2 -1
- package/skills/lark-drive/references/lark-drive-export.md +3 -0
- package/skills/lark-drive/references/lark-drive-task-result.md +3 -0
- package/skills/lark-drive/references/lark-drive-update-title.md +78 -0
- package/skills/lark-event/SKILL.md +7 -4
- package/skills/lark-event/references/lark-event-vc.md +8 -2
- package/skills/lark-im/SKILL.md +8 -8
- package/skills/lark-im/references/lark-im-chat-list.md +9 -2
- package/skills/lark-im/references/lark-im-chat-members-list.md +7 -4
- package/skills/lark-im/references/lark-im-chat-messages-list.md +10 -3
- package/skills/lark-im/references/lark-im-chat-search.md +9 -2
- package/skills/lark-im/references/lark-im-feed-group-list-item.md +2 -2
- package/skills/lark-im/references/lark-im-feed-group-list.md +2 -2
- package/skills/lark-im/references/lark-im-feed-shortcut-list.md +1 -1
- package/skills/lark-im/references/lark-im-flag-list.md +2 -2
- package/skills/lark-im/references/lark-im-message-enrichment.md +1 -1
- package/skills/lark-im/references/lark-im-messages-resources-download.md +19 -25
- package/skills/lark-im/references/lark-im-messages-search.md +4 -5
- package/skills/lark-im/references/lark-im-threads-messages-list.md +8 -4
- package/skills/lark-mail/references/lark-mail-triage.md +19 -4
- package/skills/lark-minutes/SKILL.md +1 -1
- package/skills/lark-minutes/references/lark-minutes-search.md +6 -7
- package/skills/lark-shared/SKILL.md +3 -3
- package/skills/lark-sheets/SKILL.md +83 -82
- package/skills/lark-sheets/references/lark-sheets-batch-update.md +13 -58
- package/skills/lark-sheets/references/lark-sheets-chart.md +2 -1
- package/skills/lark-sheets/references/lark-sheets-conditional-format.md +1 -1
- package/skills/lark-sheets/references/lark-sheets-range-operations.md +5 -5
- package/skills/lark-sheets/references/lark-sheets-read-data.md +80 -6
- package/skills/lark-sheets/references/lark-sheets-sheet-structure.md +21 -10
- package/skills/lark-sheets/references/lark-sheets-styles-put.md +93 -0
- package/skills/lark-sheets/references/lark-sheets-visual-standards.md +2 -2
- package/skills/lark-sheets/references/lark-sheets-workbook.md +4 -3
- package/skills/lark-sheets/references/lark-sheets-write-cells.md +40 -12
- package/skills/lark-sheets/scripts/lark_detect_subtables.py +593 -0
- package/skills/lark-sheets/scripts/lark_inspect_workbook.py +188 -0
- package/skills/lark-sheets/scripts/lark_profile_table.py +614 -0
- package/skills/lark-sheets/scripts/lark_sheet_range.py +176 -0
- package/skills/lark-sheets/scripts/lark_sheet_read_cli.py +184 -0
- package/skills/lark-sheets/scripts/sheets_df.py +21 -3
- package/skills/lark-slides/SKILL.md +27 -44
- package/skills/lark-slides/references/lark-slides-add-slide.md +92 -0
- package/skills/lark-slides/references/lark-slides-create.md +77 -65
- package/skills/lark-slides/references/lark-slides-delete-slide.md +65 -0
- package/skills/lark-slides/references/lark-slides-edit-workflows.md +6 -7
- package/skills/lark-slides/references/lark-slides-media-upload.md +3 -25
- package/skills/lark-slides/references/lark-slides-replace-slide.md +22 -1
- package/skills/lark-slides/references/lark-slides-screenshot.md +31 -13
- package/skills/lark-slides/references/lark-slides-update-slide.md +146 -0
- package/skills/lark-slides/references/lark-slides-xml-presentations-get.md +31 -8
- package/skills/lark-slides/references/slides_chart_demo.xml +1 -2
- package/skills/lark-slides/references/slides_xml_schema_definition.xml +48 -4
- package/skills/lark-slides/references/troubleshooting.md +7 -8
- package/skills/lark-slides/references/validation-checklist.md +4 -4
- package/skills/lark-slides/references/xml-schema-quick-ref.md +23 -11
- package/skills/lark-slides/scripts/sxsd_validator.py +154 -10
- package/skills/lark-slides/scripts/xml_text_overlap_lint.py +360 -76
- package/skills/lark-slides/scripts/xml_text_overlap_lint_test.py +1138 -214
- package/skills/lark-whiteboard/SKILL.md +15 -8
- package/skills/lark-whiteboard/references/lark-whiteboard-export.md +4 -3
- package/skills/lark-whiteboard/references/lark-whiteboard-update.md +4 -4
- package/skills/lark-whiteboard/references/lark-whiteboard-workflow.md +19 -17
- package/skills/lark-whiteboard/routes/dsl.md +8 -2
- package/skills/lark-whiteboard/routes/mermaid.md +1 -1
- package/skills/lark-whiteboard/routes/svg-edit.md +5 -2
- package/skills/lark-whiteboard/routes/svg.md +3 -1
- package/skills/lark-whiteboard/scenes/mention.md +71 -0
- package/skills/lark-wiki/SKILL.md +5 -3
- package/skills/lark-wiki/references/lark-wiki-delete-space.md +6 -3
- package/skills/lark-doc/references/lark-doc-word-stat.md +0 -93
- package/skills/lark-doc/references/style/lark-doc-create-workflow.md +0 -47
- package/skills/lark-doc/references/style/lark-doc-style.md +0 -68
- package/skills/lark-doc/references/style/lark-doc-update-workflow.md +0 -48
- package/skills/lark-doc/scripts/doc_word_stat.py +0 -1243
- package/skills/lark-slides/references/lark-slides-replace-pages.md +0 -95
- package/skills/lark-slides/references/lark-slides-xml-presentation-slide-create.md +0 -219
- package/skills/lark-slides/references/lark-slides-xml-presentation-slide-delete.md +0 -126
|
@@ -51,13 +51,41 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
51
51
|
f"xml-text-overlap-lint error: unexpected argument: {input_path}, need --input\n",
|
|
52
52
|
)
|
|
53
53
|
|
|
54
|
+
def test_cli_preserves_requested_symlink_path_in_result(self) -> None:
|
|
55
|
+
script_path = Path(xml_text_overlap_lint.__file__).resolve()
|
|
56
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
|
57
|
+
temp_path = Path(temp_dir)
|
|
58
|
+
resolved_path = temp_path / "resolved.xml"
|
|
59
|
+
requested_path = temp_path / "requested.xml"
|
|
60
|
+
resolved_path.write_text(
|
|
61
|
+
'<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">'
|
|
62
|
+
'<slide xmlns="https://www.larkoffice.com/sml/2.0"><data>'
|
|
63
|
+
'<shape type="text" topLeftX="10" topLeftY="10" width="100" height="30">'
|
|
64
|
+
'<content><p><span>Test</span></p></content>'
|
|
65
|
+
'</shape></data></slide>'
|
|
66
|
+
'</presentation>',
|
|
67
|
+
encoding="utf-8",
|
|
68
|
+
)
|
|
69
|
+
requested_path.symlink_to(resolved_path)
|
|
70
|
+
|
|
71
|
+
completed = subprocess.run(
|
|
72
|
+
[sys.executable, str(script_path), "--input", str(requested_path)],
|
|
73
|
+
capture_output=True,
|
|
74
|
+
check=False,
|
|
75
|
+
text=True,
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
self.assertEqual(completed.returncode, 0, completed.stderr)
|
|
79
|
+
result = json.loads(completed.stdout)
|
|
80
|
+
self.assertEqual(result["file"], str(requested_path))
|
|
81
|
+
|
|
54
82
|
def test_cli_reports_structured_slide_sxsd_error_outside_skill_directory(self) -> None:
|
|
55
83
|
script_path = Path(xml_text_overlap_lint.__file__).resolve()
|
|
56
84
|
with tempfile.TemporaryDirectory() as temp_dir:
|
|
57
85
|
input_path = Path(temp_dir) / "invalid-slide.xml"
|
|
58
86
|
input_path.write_text(
|
|
59
87
|
"""
|
|
60
|
-
<slide xmlns="
|
|
88
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
61
89
|
<data><shape type="text" topLeftX="10" topLeftY="20" width="300"/></data>
|
|
62
90
|
</slide>
|
|
63
91
|
""",
|
|
@@ -85,8 +113,8 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
85
113
|
def test_xml_text_overlap_lint_accepts_inline_fixture_xml_samples(self) -> None:
|
|
86
114
|
samples = {
|
|
87
115
|
"image-led-cover": """
|
|
88
|
-
<presentation xmlns="
|
|
89
|
-
<slide xmlns="
|
|
116
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
117
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
90
118
|
<style><fill><fillColor color="rgb(15,23,42)"/></fill></style>
|
|
91
119
|
<data>
|
|
92
120
|
<img src="tok" topLeftX="560" topLeftY="0" width="400" height="540"/>
|
|
@@ -101,8 +129,8 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
101
129
|
</presentation>
|
|
102
130
|
""",
|
|
103
131
|
"content-grid": """
|
|
104
|
-
<presentation xmlns="
|
|
105
|
-
<slide xmlns="
|
|
132
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
133
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
106
134
|
<data>
|
|
107
135
|
<shape type="text" topLeftX="60" topLeftY="44" width="620" height="46">
|
|
108
136
|
<content textType="title"><p><span fontSize="30">Execution Snapshot</span></p></content>
|
|
@@ -136,7 +164,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
136
164
|
def test_lint_xml_reports_unescaped_ampersand_in_text(self) -> None:
|
|
137
165
|
result = xml_text_overlap_lint.lint_xml(
|
|
138
166
|
"""
|
|
139
|
-
<slide xmlns="
|
|
167
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
140
168
|
<data>
|
|
141
169
|
<shape type="text" topLeftX="80" topLeftY="80" width="300" height="60">
|
|
142
170
|
<content textType="body"><p>Q&A</p></content>
|
|
@@ -156,7 +184,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
156
184
|
def test_lint_xml_reports_unescaped_ampersand_in_attribute(self) -> None:
|
|
157
185
|
result = xml_text_overlap_lint.lint_xml(
|
|
158
186
|
"""
|
|
159
|
-
<slide xmlns="
|
|
187
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
160
188
|
<data>
|
|
161
189
|
<shape type="text" topLeftX="80" topLeftY="80" width="300" height="60">
|
|
162
190
|
<content textType="body"><p><a href="https://example.com/?a=1&b=2">link</a></p></content>
|
|
@@ -173,7 +201,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
173
201
|
def test_lint_xml_reports_mismatched_xml_tag(self) -> None:
|
|
174
202
|
result = xml_text_overlap_lint.lint_xml(
|
|
175
203
|
"""
|
|
176
|
-
<slide xmlns="
|
|
204
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
177
205
|
<data>
|
|
178
206
|
<shape type="text" topLeftX="80" topLeftY="80" width="300" height="60">
|
|
179
207
|
<content textType="body"><p>Broken XML</content>
|
|
@@ -189,13 +217,15 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
189
217
|
self.assertIsInstance(issue["line"], int)
|
|
190
218
|
self.assertIsInstance(issue["column"], int)
|
|
191
219
|
self.assertIn("Broken XML", issue["context"])
|
|
220
|
+
self.assertEqual(issue["related_objects"], [])
|
|
221
|
+
self.assertNotIn("Locate via related_objects[].xml_path.", issue["hint"])
|
|
192
222
|
|
|
193
223
|
def test_lint_xml_rejects_prefixed_sml_tags(self) -> None:
|
|
194
224
|
result = xml_text_overlap_lint.lint_xml(
|
|
195
225
|
"""
|
|
196
|
-
<ns0:slide xmlns:ns0="
|
|
226
|
+
<ns0:slide xmlns:ns0="https://www.larkoffice.com/sml/2.0">
|
|
197
227
|
<ns0:data>
|
|
198
|
-
<sml:shape xmlns:sml="
|
|
228
|
+
<sml:shape xmlns:sml="https://www.larkoffice.com/sml/2.0" type="text" topLeftX="80" topLeftY="80" width="300" height="60">
|
|
199
229
|
<sml:content textType="body"><sml:p>Prefixed SML</sml:p></sml:content>
|
|
200
230
|
</sml:shape>
|
|
201
231
|
</ns0:data>
|
|
@@ -207,6 +237,29 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
207
237
|
self.assertEqual([issue["code"] for issue in issues], ["sml_prefixed_tag"] * 5)
|
|
208
238
|
self.assertEqual(issues[0]["tag"], "ns0:slide")
|
|
209
239
|
self.assertIn("default namespace", issues[0]["hint"])
|
|
240
|
+
self.assertEqual({issue["namespace"] for issue in issues}, {SML_NAMESPACE})
|
|
241
|
+
|
|
242
|
+
def test_lint_xml_reports_bound_namespace_for_prefixed_sml_tags(self) -> None:
|
|
243
|
+
for namespace in (
|
|
244
|
+
"http://www.larkoffice.com/sml/2.0",
|
|
245
|
+
"/sml/2.0",
|
|
246
|
+
SML_NAMESPACE,
|
|
247
|
+
):
|
|
248
|
+
with self.subTest(namespace=namespace):
|
|
249
|
+
result = xml_text_overlap_lint.lint_xml(
|
|
250
|
+
f"""
|
|
251
|
+
<sml:slide xmlns:sml="{namespace}">
|
|
252
|
+
<sml:data>
|
|
253
|
+
<sml:shape type="text" topLeftX="80" topLeftY="80" width="300" height="60">
|
|
254
|
+
<sml:content textType="body"><sml:p>Prefixed SML</sml:p></sml:content>
|
|
255
|
+
</sml:shape>
|
|
256
|
+
</sml:data>
|
|
257
|
+
</sml:slide>
|
|
258
|
+
"""
|
|
259
|
+
)
|
|
260
|
+
issues = result["issues"]
|
|
261
|
+
self.assertEqual([issue["code"] for issue in issues], ["sml_prefixed_tag"] * 5)
|
|
262
|
+
self.assertEqual({issue["namespace"] for issue in issues}, {namespace})
|
|
210
263
|
|
|
211
264
|
def test_lint_xml_accepts_server_readback_slide_without_namespace(self) -> None:
|
|
212
265
|
result = xml_text_overlap_lint.lint_xml(
|
|
@@ -258,6 +311,24 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
258
311
|
self.assertEqual(result["summary"]["slide_count"], 1)
|
|
259
312
|
self.assertEqual(result["summary"]["error_count"], 0)
|
|
260
313
|
|
|
314
|
+
def test_lint_xml_accepts_legacy_http_namespace(self) -> None:
|
|
315
|
+
result = xml_text_overlap_lint.lint_xml(
|
|
316
|
+
"""
|
|
317
|
+
<presentation xmlns="http://www.larkoffice.com/sml/2.0" width="960" height="540" id="legacy-http-id">
|
|
318
|
+
<slide id="server-slide-id">
|
|
319
|
+
<data>
|
|
320
|
+
<shape id="server-shape-id" type="text" topLeftX="80" topLeftY="80" width="300" height="60">
|
|
321
|
+
<content textType="body"><p>Legacy HTTP namespace</p></content>
|
|
322
|
+
</shape>
|
|
323
|
+
</data>
|
|
324
|
+
</slide>
|
|
325
|
+
</presentation>
|
|
326
|
+
"""
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
self.assertEqual(result["summary"]["slide_count"], 1)
|
|
330
|
+
self.assertEqual(result["summary"]["error_count"], 0)
|
|
331
|
+
|
|
261
332
|
def test_lint_xml_rejects_server_readback_presentation_wrong_namespace(self) -> None:
|
|
262
333
|
result = xml_text_overlap_lint.lint_xml(
|
|
263
334
|
"""
|
|
@@ -272,7 +343,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
272
343
|
|
|
273
344
|
def test_lint_xml_rejects_xml_declaration(self) -> None:
|
|
274
345
|
result = xml_text_overlap_lint.lint_xml(
|
|
275
|
-
'<?xml version="1.0"?><slide xmlns="
|
|
346
|
+
'<?xml version="1.0"?><slide xmlns="https://www.larkoffice.com/sml/2.0"><data/></slide>'
|
|
276
347
|
)
|
|
277
348
|
|
|
278
349
|
self.assertEqual(result["summary"]["error_count"], 1)
|
|
@@ -281,7 +352,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
281
352
|
def test_lint_xml_reports_missing_required_sxsd_attribute(self) -> None:
|
|
282
353
|
result = xml_text_overlap_lint.lint_xml(
|
|
283
354
|
"""
|
|
284
|
-
<slide xmlns="
|
|
355
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
285
356
|
<data><shape type="text" topLeftX="80" topLeftY="80" width="300"/></data>
|
|
286
357
|
</slide>
|
|
287
358
|
"""
|
|
@@ -296,7 +367,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
296
367
|
def test_lint_xml_rejects_child_order_that_violates_xsd_sequence(self) -> None:
|
|
297
368
|
result = xml_text_overlap_lint.lint_xml(
|
|
298
369
|
"""
|
|
299
|
-
<presentation xmlns="
|
|
370
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
300
371
|
<slide/>
|
|
301
372
|
<title>Late title</title>
|
|
302
373
|
</presentation>
|
|
@@ -309,7 +380,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
309
380
|
def test_lint_xml_accepts_escaped_entities_without_suspicious_entity_warning(self) -> None:
|
|
310
381
|
result = xml_text_overlap_lint.lint_xml(
|
|
311
382
|
"""
|
|
312
|
-
<slide xmlns="
|
|
383
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
313
384
|
<data>
|
|
314
385
|
<shape type="text" topLeftX="80" topLeftY="80" width="300" height="60">
|
|
315
386
|
<content textType="body"><p>Q&A</p></content>
|
|
@@ -324,7 +395,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
324
395
|
def test_lint_xml_accepts_chinese_full_width_punctuation(self) -> None:
|
|
325
396
|
result = xml_text_overlap_lint.lint_xml(
|
|
326
397
|
"""
|
|
327
|
-
<slide xmlns="
|
|
398
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
328
399
|
<data>
|
|
329
400
|
<shape type="text" topLeftX="80" topLeftY="80" width="620" height="90">
|
|
330
401
|
<content textType="body"><p>承诺:按期交付;持续复盘|风险透明</p></content>
|
|
@@ -338,7 +409,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
338
409
|
def test_lint_xml_single_slide_reports_out_of_canvas_and_blank_slide_errors(self) -> None:
|
|
339
410
|
result = xml_text_overlap_lint.lint_xml(
|
|
340
411
|
"""
|
|
341
|
-
<slide xmlns="
|
|
412
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
342
413
|
<data>
|
|
343
414
|
<shape type="text" topLeftX="1000" topLeftY="500" width="120" height="80">
|
|
344
415
|
<content textType="body"><p>Body text outside the canvas</p></content>
|
|
@@ -358,15 +429,15 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
358
429
|
def test_lint_xml_preserves_presentation_canvas_and_slide_order(self) -> None:
|
|
359
430
|
result = xml_text_overlap_lint.lint_xml(
|
|
360
431
|
"""
|
|
361
|
-
<presentation xmlns="
|
|
362
|
-
<slide xmlns="
|
|
432
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="1280" height="720">
|
|
433
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
363
434
|
<data>
|
|
364
435
|
<shape id="first" type="text" topLeftX="80" topLeftY="80" width="300" height="60">
|
|
365
436
|
<content textType="body"><p>First slide</p></content>
|
|
366
437
|
</shape>
|
|
367
438
|
</data>
|
|
368
439
|
</slide>
|
|
369
|
-
<slide xmlns="
|
|
440
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
370
441
|
<data>
|
|
371
442
|
<img id="second" src="tok" topLeftX="100" topLeftY="120" width="240" height="160"/>
|
|
372
443
|
<shape id="second-shape" type="text" topLeftX="80" topLeftY="80" width="300" height="60">
|
|
@@ -387,7 +458,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
387
458
|
def test_lint_xml_handles_self_closing_slide_before_normal_slide(self) -> None:
|
|
388
459
|
result = xml_text_overlap_lint.lint_xml(
|
|
389
460
|
"""
|
|
390
|
-
<presentation xmlns="
|
|
461
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
391
462
|
<slide/>
|
|
392
463
|
<slide>
|
|
393
464
|
<data>
|
|
@@ -410,7 +481,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
410
481
|
def test_lint_xml_keeps_trailing_self_closing_slide(self) -> None:
|
|
411
482
|
result = xml_text_overlap_lint.lint_xml(
|
|
412
483
|
"""
|
|
413
|
-
<presentation xmlns="
|
|
484
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
414
485
|
<slide>
|
|
415
486
|
<data>
|
|
416
487
|
<shape type="text" topLeftX="80" topLeftY="80" width="300" height="60">
|
|
@@ -432,7 +503,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
432
503
|
def test_lint_xml_ignores_slide_markup_inside_xml_comments(self) -> None:
|
|
433
504
|
result = xml_text_overlap_lint.lint_xml(
|
|
434
505
|
"""
|
|
435
|
-
<presentation xmlns="
|
|
506
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
436
507
|
<slide>
|
|
437
508
|
<data>
|
|
438
509
|
<shape type="text" topLeftX="80" topLeftY="80" width="300" height="60">
|
|
@@ -451,7 +522,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
451
522
|
def test_lint_xml_ignores_invalid_slide_markup_inside_xml_comments(self) -> None:
|
|
452
523
|
result = xml_text_overlap_lint.lint_xml(
|
|
453
524
|
"""
|
|
454
|
-
<presentation xmlns="
|
|
525
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
455
526
|
<slide><data/></slide>
|
|
456
527
|
<!-- Old draft: <slide bogus="x"/> -->
|
|
457
528
|
</presentation>
|
|
@@ -467,7 +538,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
467
538
|
def test_lint_xml_skips_only_invalid_slide_and_continues_geometry_checks(self) -> None:
|
|
468
539
|
result = xml_text_overlap_lint.lint_xml(
|
|
469
540
|
"""
|
|
470
|
-
<presentation xmlns="
|
|
541
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
471
542
|
<slide>
|
|
472
543
|
<data>
|
|
473
544
|
<shape id="invalid" type="text" topLeftX="1000" topLeftY="80" width="300">
|
|
@@ -504,7 +575,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
504
575
|
def test_lint_xml_scopes_invalid_slide_root_attribute_to_that_slide(self) -> None:
|
|
505
576
|
result = xml_text_overlap_lint.lint_xml(
|
|
506
577
|
"""
|
|
507
|
-
<presentation xmlns="
|
|
578
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
508
579
|
<slide bogusAttr="oops">
|
|
509
580
|
<data><shape type="rect" topLeftX="80" topLeftY="80" width="100" height="100"/></data>
|
|
510
581
|
</slide>
|
|
@@ -525,6 +596,118 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
525
596
|
[issue["code"] for issue in result["slides"][1]["errors"]],
|
|
526
597
|
)
|
|
527
598
|
|
|
599
|
+
def test_lint_xml_allows_svg_subtree_inside_embed(self) -> None:
|
|
600
|
+
result = xml_text_overlap_lint.lint_xml(
|
|
601
|
+
"""
|
|
602
|
+
<slide xmlns="http://www.larkoffice.com/sml/2.0">
|
|
603
|
+
<data>
|
|
604
|
+
<embed topLeftX="80" topLeftY="120" width="240" height="140">
|
|
605
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 140">
|
|
606
|
+
<rect x="10" y="10" width="220" height="120" rx="12" fill="#EFF6FF"/>
|
|
607
|
+
<circle cx="70" cy="70" r="34" fill="#2563EB"/>
|
|
608
|
+
<text x="130" y="76" font-size="18" fill="#1E3A8A">SVG OK</text>
|
|
609
|
+
<foreignObject x="0" y="0" width="1" height="1">
|
|
610
|
+
<embed xmlns="http://www.w3.org/1999/xhtml">
|
|
611
|
+
<rect xmlns="http://www.w3.org/2000/svg" width="1" height="1"/>
|
|
612
|
+
</embed>
|
|
613
|
+
</foreignObject>
|
|
614
|
+
</svg>
|
|
615
|
+
</embed>
|
|
616
|
+
</data>
|
|
617
|
+
</slide>
|
|
618
|
+
"""
|
|
619
|
+
)
|
|
620
|
+
codes = [issue["code"] for issue in result["slides"][0]["issues"]]
|
|
621
|
+
self.assertNotIn("sxsd_unsupported_tag", codes)
|
|
622
|
+
self.assertNotIn("sxsd_unsupported_attr", codes)
|
|
623
|
+
self.assertEqual(result["summary"]["error_count"], 0)
|
|
624
|
+
|
|
625
|
+
def test_lint_xml_enforces_embed_svg_contract(self) -> None:
|
|
626
|
+
cases = [
|
|
627
|
+
("missing SVG", "", "sxsd_missing_required_child"),
|
|
628
|
+
("wrong namespace", '<svg viewBox="0 0 20 20"/>', "sxsd_unsupported_tag"),
|
|
629
|
+
(
|
|
630
|
+
"multiple SVG roots",
|
|
631
|
+
'<svg xmlns="http://www.w3.org/2000/svg"/><svg xmlns="http://www.w3.org/2000/svg"/>',
|
|
632
|
+
"sxsd_too_many_children",
|
|
633
|
+
),
|
|
634
|
+
(
|
|
635
|
+
"non-SVG root element",
|
|
636
|
+
'<rect xmlns="http://www.w3.org/2000/svg" width="20" height="20"/>',
|
|
637
|
+
"sxsd_unexpected_child",
|
|
638
|
+
),
|
|
639
|
+
(
|
|
640
|
+
"SVG after reflection",
|
|
641
|
+
'<reflection/><svg xmlns="http://www.w3.org/2000/svg"/>',
|
|
642
|
+
"sxsd_invalid_child_order",
|
|
643
|
+
),
|
|
644
|
+
]
|
|
645
|
+
for name, children, expected_code in cases:
|
|
646
|
+
with self.subTest(name=name):
|
|
647
|
+
result = xml_text_overlap_lint.lint_xml(
|
|
648
|
+
f"""
|
|
649
|
+
<slide xmlns="http://www.larkoffice.com/sml/2.0">
|
|
650
|
+
<data>
|
|
651
|
+
<embed topLeftX="80" topLeftY="120" width="240" height="140">
|
|
652
|
+
{children}
|
|
653
|
+
</embed>
|
|
654
|
+
</data>
|
|
655
|
+
</slide>
|
|
656
|
+
"""
|
|
657
|
+
)
|
|
658
|
+
codes = [issue["code"] for issue in result["slides"][0]["issues"]]
|
|
659
|
+
self.assertIn(expected_code, codes)
|
|
660
|
+
|
|
661
|
+
def test_lint_xml_enforces_embed_svg_root_for_readback_namespaces(self) -> None:
|
|
662
|
+
document_templates = [
|
|
663
|
+
("bare slide", "<slide>{content}</slide>"),
|
|
664
|
+
(
|
|
665
|
+
"short namespace",
|
|
666
|
+
'<presentation xmlns="/sml/2.0" width="960" height="540">'
|
|
667
|
+
"<slide>{content}</slide>"
|
|
668
|
+
"</presentation>",
|
|
669
|
+
),
|
|
670
|
+
(
|
|
671
|
+
"HTTPS namespace",
|
|
672
|
+
'<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">'
|
|
673
|
+
"<slide>{content}</slide>"
|
|
674
|
+
"</presentation>",
|
|
675
|
+
),
|
|
676
|
+
]
|
|
677
|
+
embed_template = """
|
|
678
|
+
<data>
|
|
679
|
+
<embed topLeftX="80" topLeftY="120" width="240" height="140">
|
|
680
|
+
{svg_root}
|
|
681
|
+
</embed>
|
|
682
|
+
</data>
|
|
683
|
+
"""
|
|
684
|
+
roots = [
|
|
685
|
+
("valid SVG root", '<svg xmlns="http://www.w3.org/2000/svg"/>', False),
|
|
686
|
+
(
|
|
687
|
+
"non-SVG root element",
|
|
688
|
+
'<rect xmlns="http://www.w3.org/2000/svg" width="20" height="20"/>',
|
|
689
|
+
True,
|
|
690
|
+
),
|
|
691
|
+
]
|
|
692
|
+
|
|
693
|
+
for document_name, document_template in document_templates:
|
|
694
|
+
for root_name, svg_root, should_error in roots:
|
|
695
|
+
with self.subTest(document=document_name, root=root_name):
|
|
696
|
+
content = embed_template.format(svg_root=svg_root)
|
|
697
|
+
result = xml_text_overlap_lint.lint_xml(
|
|
698
|
+
document_template.format(content=content)
|
|
699
|
+
)
|
|
700
|
+
codes = [
|
|
701
|
+
issue["code"]
|
|
702
|
+
for slide in result["slides"]
|
|
703
|
+
for issue in slide["issues"]
|
|
704
|
+
]
|
|
705
|
+
if should_error:
|
|
706
|
+
self.assertIn("sxsd_unexpected_child", codes)
|
|
707
|
+
else:
|
|
708
|
+
self.assertNotIn("sxsd_unexpected_child", codes)
|
|
709
|
+
self.assertEqual(result["summary"]["error_count"], 0)
|
|
710
|
+
|
|
528
711
|
def test_lint_xml_reports_sxsd_unsupported_tag_with_alias_hint(self) -> None:
|
|
529
712
|
cases = [
|
|
530
713
|
("textbox", '<textbox topLeftX="80" topLeftY="80" width="300" height="60">Text</textbox>', '<shape type="text">'),
|
|
@@ -534,7 +717,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
534
717
|
with self.subTest(tag=tag_name):
|
|
535
718
|
result = xml_text_overlap_lint.lint_xml(
|
|
536
719
|
f"""
|
|
537
|
-
<slide xmlns="
|
|
720
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
538
721
|
<data>{element_xml}</data>
|
|
539
722
|
</slide>
|
|
540
723
|
"""
|
|
@@ -562,7 +745,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
562
745
|
with self.subTest(attr=attr_name):
|
|
563
746
|
result = xml_text_overlap_lint.lint_xml(
|
|
564
747
|
f"""
|
|
565
|
-
<slide xmlns="
|
|
748
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
566
749
|
<data>{element_xml}</data>
|
|
567
750
|
</slide>
|
|
568
751
|
"""
|
|
@@ -584,7 +767,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
584
767
|
def test_lint_xml_keeps_unrelated_unsupported_and_missing_attrs(self) -> None:
|
|
585
768
|
result = xml_text_overlap_lint.lint_xml(
|
|
586
769
|
"""
|
|
587
|
-
<slide xmlns="
|
|
770
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
588
771
|
<data>
|
|
589
772
|
<shape type="text" bogus="x" topLeftX="80" topLeftY="80" width="300"/>
|
|
590
773
|
</data>
|
|
@@ -600,7 +783,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
600
783
|
def test_lint_xml_keeps_missing_attrs_when_suggestion_is_ambiguous(self) -> None:
|
|
601
784
|
result = xml_text_overlap_lint.lint_xml(
|
|
602
785
|
"""
|
|
603
|
-
<slide xmlns="
|
|
786
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
604
787
|
<data>
|
|
605
788
|
<shape type="text" topLeft="80" width="300" height="60"/>
|
|
606
789
|
</data>
|
|
@@ -620,7 +803,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
620
803
|
def test_lint_xml_suppresses_only_missing_attr_that_resolves_ambiguous_suggestion(self) -> None:
|
|
621
804
|
result = xml_text_overlap_lint.lint_xml(
|
|
622
805
|
"""
|
|
623
|
-
<slide xmlns="
|
|
806
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
624
807
|
<data>
|
|
625
808
|
<shape type="text" topLeftXX="80" topLeftY="80" width="300" height="60"/>
|
|
626
809
|
</data>
|
|
@@ -639,7 +822,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
639
822
|
def test_lint_xml_ignores_server_filled_id_attrs(self) -> None:
|
|
640
823
|
result = xml_text_overlap_lint.lint_xml(
|
|
641
824
|
"""
|
|
642
|
-
<slide id="server-slide-id" xmlns="
|
|
825
|
+
<slide id="server-slide-id" xmlns="https://www.larkoffice.com/sml/2.0">
|
|
643
826
|
<data>
|
|
644
827
|
<shape id="server-shape-id" type="rect" topLeftX="80" topLeftY="80" width="300" height="160">
|
|
645
828
|
<fill id="server-fill-id" unexpected="value">
|
|
@@ -660,7 +843,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
660
843
|
def test_lint_xml_ignores_chart_roundtrip_attrs(self) -> None:
|
|
661
844
|
result = xml_text_overlap_lint.lint_xml(
|
|
662
845
|
"""
|
|
663
|
-
<slide xmlns="
|
|
846
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
664
847
|
<data>
|
|
665
848
|
<chart updated="true" topLeftX="80" topLeftY="80" width="300" height="160">
|
|
666
849
|
<chartPlotArea><chartPlot type="line"/></chartPlotArea>
|
|
@@ -679,7 +862,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
679
862
|
def test_lint_xml_ignores_chart_parsed_values_roundtrip_tags(self) -> None:
|
|
680
863
|
result = xml_text_overlap_lint.lint_xml(
|
|
681
864
|
"""
|
|
682
|
-
<slide xmlns="
|
|
865
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
683
866
|
<data>
|
|
684
867
|
<chart topLeftX="80" topLeftY="80" width="300" height="160">
|
|
685
868
|
<chartPlotArea><chartPlot type="line"/></chartPlotArea>
|
|
@@ -702,7 +885,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
702
885
|
def test_lint_xml_ignores_chart_parsed_values_roundtrip_tag(self) -> None:
|
|
703
886
|
result = xml_text_overlap_lint.lint_xml(
|
|
704
887
|
"""
|
|
705
|
-
<slide xmlns="
|
|
888
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
706
889
|
<data>
|
|
707
890
|
<chart topLeftX="80" topLeftY="80" width="300" height="160">
|
|
708
891
|
<chartPlotArea><chartPlot type="line"/></chartPlotArea>
|
|
@@ -726,7 +909,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
726
909
|
def test_lint_xml_rejects_chart_parsed_values_outside_chart_field(self) -> None:
|
|
727
910
|
result = xml_text_overlap_lint.lint_xml(
|
|
728
911
|
"""
|
|
729
|
-
<slide xmlns="
|
|
912
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
730
913
|
<data>
|
|
731
914
|
<shape type="rect" topLeftX="80" topLeftY="80" width="300" height="160">
|
|
732
915
|
<chartParsedValues>unexpected</chartParsedValues>
|
|
@@ -749,7 +932,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
749
932
|
def test_lint_xml_limits_chart_roundtrip_attrs_to_matching_tags(self) -> None:
|
|
750
933
|
result = xml_text_overlap_lint.lint_xml(
|
|
751
934
|
"""
|
|
752
|
-
<slide xmlns="
|
|
935
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
753
936
|
<data>
|
|
754
937
|
<chart isStaticData="true" topLeftX="80" topLeftY="80" width="300" height="160">
|
|
755
938
|
<chartPlotArea><chartPlot type="line"/></chartPlotArea>
|
|
@@ -774,7 +957,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
774
957
|
def test_lint_xml_reports_gradient_shorthand_attrs_on_fill_color(self) -> None:
|
|
775
958
|
result = xml_text_overlap_lint.lint_xml(
|
|
776
959
|
"""
|
|
777
|
-
<slide xmlns="
|
|
960
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
778
961
|
<data>
|
|
779
962
|
<shape type="rect" topLeftX="80" topLeftY="80" width="300" height="160">
|
|
780
963
|
<fill>
|
|
@@ -804,7 +987,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
804
987
|
def test_lint_xml_accepts_chart_field_simple_content_attrs(self) -> None:
|
|
805
988
|
result = xml_text_overlap_lint.lint_xml(
|
|
806
989
|
"""
|
|
807
|
-
<slide xmlns="
|
|
990
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
808
991
|
<data>
|
|
809
992
|
<chart topLeftX="80" topLeftY="80" width="520" height="320">
|
|
810
993
|
<chartPlotArea>
|
|
@@ -836,7 +1019,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
836
1019
|
try:
|
|
837
1020
|
result = xml_text_overlap_lint.lint_xml(
|
|
838
1021
|
"""
|
|
839
|
-
<slide xmlns="
|
|
1022
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
840
1023
|
<data>
|
|
841
1024
|
<shape type="text" topLeftX="80" topLeftY="80" width="300" height="60">
|
|
842
1025
|
<content><p>No icons here</p></content>
|
|
@@ -854,7 +1037,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
854
1037
|
def test_lint_xml_accepts_iconpark_icon_type_from_index(self) -> None:
|
|
855
1038
|
result = xml_text_overlap_lint.lint_xml(
|
|
856
1039
|
"""
|
|
857
|
-
<slide xmlns="
|
|
1040
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
858
1041
|
<data>
|
|
859
1042
|
<icon iconType="iconpark/Base/setting.svg" topLeftX="80" topLeftY="80" width="48" height="48">
|
|
860
1043
|
<fill><fillColor color="rgba(37, 99, 235, 1)"/></fill>
|
|
@@ -879,7 +1062,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
879
1062
|
with self.subTest(icon=icon_xml):
|
|
880
1063
|
result = xml_text_overlap_lint.lint_xml(
|
|
881
1064
|
f"""
|
|
882
|
-
<slide xmlns="
|
|
1065
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
883
1066
|
<data>{icon_xml}</data>
|
|
884
1067
|
</slide>
|
|
885
1068
|
"""
|
|
@@ -893,7 +1076,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
893
1076
|
def test_lint_xml_reports_icon_transparent_fill_color(self) -> None:
|
|
894
1077
|
result = xml_text_overlap_lint.lint_xml(
|
|
895
1078
|
"""
|
|
896
|
-
<slide xmlns="
|
|
1079
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
897
1080
|
<data>
|
|
898
1081
|
<icon iconType="iconpark/Base/setting.svg" topLeftX="80" topLeftY="80" width="48" height="48">
|
|
899
1082
|
<fill><fillColor color="rgba(37, 99, 235, 0)"/></fill>
|
|
@@ -911,7 +1094,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
911
1094
|
def test_lint_xml_reports_iconpark_icon_type_outside_index(self) -> None:
|
|
912
1095
|
result = xml_text_overlap_lint.lint_xml(
|
|
913
1096
|
"""
|
|
914
|
-
<slide xmlns="
|
|
1097
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
915
1098
|
<data>
|
|
916
1099
|
<icon iconType="iconpark/Base/settng.svg" topLeftX="80" topLeftY="80" width="48" height="48">
|
|
917
1100
|
<fill><fillColor color="rgba(37, 99, 235, 1)"/></fill>
|
|
@@ -929,11 +1112,34 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
929
1112
|
self.assertIn("iconpark-index.json", issue["hint"])
|
|
930
1113
|
self.assertIn("iconpark/Base/setting.svg", issue["hint"])
|
|
931
1114
|
|
|
1115
|
+
def test_lint_xml_skips_iconpark_validation_inside_embedded_svg(self) -> None:
|
|
1116
|
+
result = xml_text_overlap_lint.lint_xml(
|
|
1117
|
+
"""
|
|
1118
|
+
<slide xmlns="http://www.larkoffice.com/sml/2.0">
|
|
1119
|
+
<data>
|
|
1120
|
+
<embed topLeftX="80" topLeftY="120" width="240" height="140">
|
|
1121
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 140">
|
|
1122
|
+
<rect x="10" y="10" width="220" height="120" fill="#EFF6FF"/>
|
|
1123
|
+
<icon iconType="not-an-iconpark-name"/>
|
|
1124
|
+
<foreignObject x="0" y="0" width="60" height="60">
|
|
1125
|
+
<icon xmlns="http://www.w3.org/1999/xhtml" iconType="not-an-iconpark-name"/>
|
|
1126
|
+
</foreignObject>
|
|
1127
|
+
</svg>
|
|
1128
|
+
</embed>
|
|
1129
|
+
</data>
|
|
1130
|
+
</slide>
|
|
1131
|
+
"""
|
|
1132
|
+
)
|
|
1133
|
+
codes = [issue["code"] for issue in result["document"]["errors"]]
|
|
1134
|
+
self.assertNotIn("iconpark_unsupported_icon_type", codes)
|
|
1135
|
+
self.assertNotIn("icon_missing_fill_color", codes)
|
|
1136
|
+
self.assertEqual(result["summary"]["error_count"], 0)
|
|
1137
|
+
|
|
932
1138
|
def test_lint_xml_detects_overlapping_text_boxes(self) -> None:
|
|
933
1139
|
result = xml_text_overlap_lint.lint_xml(
|
|
934
1140
|
"""
|
|
935
|
-
<presentation xmlns="
|
|
936
|
-
<slide xmlns="
|
|
1141
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
1142
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
937
1143
|
<data>
|
|
938
1144
|
<shape type="text" topLeftX="80" topLeftY="80" width="300" height="60">
|
|
939
1145
|
<content textType="title"><p>Title</p></content>
|
|
@@ -953,7 +1159,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
953
1159
|
def test_lint_xml_detects_current_itinerary_cjk_caption_occlusion(self) -> None:
|
|
954
1160
|
result = xml_text_overlap_lint.lint_xml(
|
|
955
1161
|
"""
|
|
956
|
-
<slide id="pQO" xmlns="
|
|
1162
|
+
<slide id="pQO" xmlns="https://www.larkoffice.com/sml/2.0">
|
|
957
1163
|
<data>
|
|
958
1164
|
<shape width="190" height="80" topLeftX="580" topLeftY="170" presetHandlers="0" type="rect" id="blI">
|
|
959
1165
|
<fill><fillColor color="rgba(255, 255, 255, 0.9)"/></fill>
|
|
@@ -1011,7 +1217,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1011
1217
|
def test_lint_xml_detects_horizontal_text_overflow_across_declared_box_gap(self) -> None:
|
|
1012
1218
|
result = xml_text_overlap_lint.lint_xml(
|
|
1013
1219
|
"""
|
|
1014
|
-
<slide xmlns="
|
|
1220
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1015
1221
|
<data>
|
|
1016
1222
|
<shape id="source" type="text" topLeftX="80" topLeftY="100" width="160" height="40">
|
|
1017
1223
|
<content fontSize="18" wrap="false"><p>这是一个足够长的中文文本用于检测跨越间隙的横向溢出</p></content>
|
|
@@ -1034,7 +1240,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1034
1240
|
def test_lint_xml_allows_horizontal_text_with_default_wrap(self) -> None:
|
|
1035
1241
|
result = xml_text_overlap_lint.lint_xml(
|
|
1036
1242
|
"""
|
|
1037
|
-
<slide xmlns="
|
|
1243
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1038
1244
|
<data>
|
|
1039
1245
|
<shape id="source" type="text" topLeftX="80" topLeftY="100" width="160" height="40">
|
|
1040
1246
|
<content fontSize="18"><p>这是一个足够长的中文文本用于检测默认自动换行</p></content>
|
|
@@ -1055,8 +1261,8 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1055
1261
|
def test_lint_xml_reports_text_out_of_canvas_and_warns_for_text_height(self) -> None:
|
|
1056
1262
|
result = xml_text_overlap_lint.lint_xml(
|
|
1057
1263
|
"""
|
|
1058
|
-
<presentation xmlns="
|
|
1059
|
-
<slide xmlns="
|
|
1264
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
1265
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1060
1266
|
<data>
|
|
1061
1267
|
<shape type="text" topLeftX="80" topLeftY="80" width="180" height="20">
|
|
1062
1268
|
<content textType="body" fontSize="18"><p>This paragraph is intentionally much longer than the box can safely contain.</p></content>
|
|
@@ -1078,7 +1284,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1078
1284
|
def test_lint_xml_warns_when_text_may_overflow_its_own_shape(self) -> None:
|
|
1079
1285
|
result = xml_text_overlap_lint.lint_xml(
|
|
1080
1286
|
"""
|
|
1081
|
-
<slide xmlns="
|
|
1287
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1082
1288
|
<data>
|
|
1083
1289
|
<shape id="overflowing" type="text" topLeftX="80" topLeftY="80" width="360" height="80">
|
|
1084
1290
|
<content fontSize="20" lineSpacing="multiple:1.5" autoFit="no-auto-fit">
|
|
@@ -1122,7 +1328,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1122
1328
|
def test_lint_xml_uses_fixed_line_spacing_for_text_height_warning(self) -> None:
|
|
1123
1329
|
result = xml_text_overlap_lint.lint_xml(
|
|
1124
1330
|
"""
|
|
1125
|
-
<slide xmlns="
|
|
1331
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1126
1332
|
<data>
|
|
1127
1333
|
<shape id="fixed-overflow" type="text" topLeftX="80" topLeftY="80" width="360" height="50">
|
|
1128
1334
|
<content fontSize="20" lineSpacing="fixed:20" autoFit="no-auto-fit">
|
|
@@ -1144,7 +1350,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1144
1350
|
def test_lint_xml_ignores_subpixel_text_height_overflow_tolerance(self) -> None:
|
|
1145
1351
|
result = xml_text_overlap_lint.lint_xml(
|
|
1146
1352
|
"""
|
|
1147
|
-
<slide xmlns="
|
|
1353
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1148
1354
|
<data>
|
|
1149
1355
|
<shape id="minor-overflow" type="text" topLeftX="80" topLeftY="80" width="360" height="39.8">
|
|
1150
1356
|
<content fontSize="20" lineSpacing="fixed:20" autoFit="no-auto-fit">
|
|
@@ -1165,7 +1371,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1165
1371
|
def test_lint_xml_allows_single_line_width_estimation_jitter(self) -> None:
|
|
1166
1372
|
result = xml_text_overlap_lint.lint_xml(
|
|
1167
1373
|
"""
|
|
1168
|
-
<slide xmlns="
|
|
1374
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1169
1375
|
<data>
|
|
1170
1376
|
<shape id="metric" type="text" topLeftX="80" topLeftY="80" width="152" height="54">
|
|
1171
1377
|
<content fontSize="36" lineSpacing="multiple:1.2" autoFit="no-auto-fit"><p>4.16万亿</p></content>
|
|
@@ -1184,7 +1390,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1184
1390
|
def test_lint_xml_allows_short_metric_text_with_separators_as_single_line(self) -> None:
|
|
1185
1391
|
result = xml_text_overlap_lint.lint_xml(
|
|
1186
1392
|
"""
|
|
1187
|
-
<slide xmlns="
|
|
1393
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1188
1394
|
<data>
|
|
1189
1395
|
<shape id="metric" type="text" topLeftX="80" topLeftY="80" width="150" height="50">
|
|
1190
1396
|
<content textType="title" fontSize="36" autoFit="no-auto-fit"><p>4.16万亿</p></content>
|
|
@@ -1206,7 +1412,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1206
1412
|
def test_lint_xml_reports_plain_short_metric_when_it_wraps(self) -> None:
|
|
1207
1413
|
result = xml_text_overlap_lint.lint_xml(
|
|
1208
1414
|
"""
|
|
1209
|
-
<slide xmlns="
|
|
1415
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1210
1416
|
<data>
|
|
1211
1417
|
<shape id="plain-age" type="text" topLeftX="80" topLeftY="80" width="50" height="80">
|
|
1212
1418
|
<content textType="title" fontSize="36" bold="true" autoFit="no-auto-fit"><p>82岁</p></content>
|
|
@@ -1226,7 +1432,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1226
1432
|
def test_lint_xml_allows_centered_short_label_near_fit_as_single_line(self) -> None:
|
|
1227
1433
|
result = xml_text_overlap_lint.lint_xml(
|
|
1228
1434
|
"""
|
|
1229
|
-
<slide xmlns="
|
|
1435
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1230
1436
|
<data>
|
|
1231
1437
|
<shape id="centered-label" type="text" topLeftX="80" topLeftY="80" width="200" height="30">
|
|
1232
1438
|
<content fontSize="14" bold="true" textAlign="center" autoFit="no-auto-fit">
|
|
@@ -1247,7 +1453,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1247
1453
|
def test_lint_xml_allows_headline_near_fit_as_single_line(self) -> None:
|
|
1248
1454
|
result = xml_text_overlap_lint.lint_xml(
|
|
1249
1455
|
"""
|
|
1250
|
-
<slide xmlns="
|
|
1456
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1251
1457
|
<data>
|
|
1252
1458
|
<shape id="headline" type="text" topLeftX="80" topLeftY="80" width="700" height="50">
|
|
1253
1459
|
<content textType="headline" fontSize="26" bold="true" lineSpacing="multiple:1.3" autoFit="no-auto-fit">
|
|
@@ -1268,7 +1474,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1268
1474
|
def test_lint_xml_allows_dense_body_line_spacing_estimation_slack(self) -> None:
|
|
1269
1475
|
result = xml_text_overlap_lint.lint_xml(
|
|
1270
1476
|
"""
|
|
1271
|
-
<slide xmlns="
|
|
1477
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1272
1478
|
<data>
|
|
1273
1479
|
<shape id="dense-body" type="text" topLeftX="80" topLeftY="80" width="360" height="140">
|
|
1274
1480
|
<content fontSize="13" bold="true" lineSpacing="multiple:1.7" autoFit="no-auto-fit">
|
|
@@ -1294,7 +1500,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1294
1500
|
def test_lint_xml_reports_dense_body_when_adjusted_height_still_overflows(self) -> None:
|
|
1295
1501
|
result = xml_text_overlap_lint.lint_xml(
|
|
1296
1502
|
"""
|
|
1297
|
-
<slide xmlns="
|
|
1503
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1298
1504
|
<data>
|
|
1299
1505
|
<shape id="dense-body" type="text" topLeftX="80" topLeftY="80" width="360" height="100">
|
|
1300
1506
|
<content fontSize="13" bold="true" lineSpacing="multiple:1.7" autoFit="no-auto-fit">
|
|
@@ -1321,7 +1527,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1321
1527
|
def test_lint_xml_reports_letter_spaced_caption_near_fit(self) -> None:
|
|
1322
1528
|
result = xml_text_overlap_lint.lint_xml(
|
|
1323
1529
|
"""
|
|
1324
|
-
<slide xmlns="
|
|
1530
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1325
1531
|
<data>
|
|
1326
1532
|
<shape id="caption" type="text" topLeftX="80" topLeftY="80" width="120" height="20">
|
|
1327
1533
|
<content textType="caption" fontSize="11" letterSpacing="1" autoFit="no-auto-fit">
|
|
@@ -1343,7 +1549,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1343
1549
|
def test_lint_xml_reports_micro_caption_when_wrapping_overflows(self) -> None:
|
|
1344
1550
|
result = xml_text_overlap_lint.lint_xml(
|
|
1345
1551
|
"""
|
|
1346
|
-
<slide xmlns="
|
|
1552
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1347
1553
|
<data>
|
|
1348
1554
|
<shape id="micro-caption" type="text" topLeftX="80" topLeftY="60" width="200" height="16">
|
|
1349
1555
|
<content textType="caption" fontSize="3" lineSpacing="multiple:1.3" letterSpacing="160" autoFit="no-auto-fit">
|
|
@@ -1365,7 +1571,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1365
1571
|
def test_lint_xml_text_may_overflow_shape_upgrades_to_error_above_threshold(self) -> None:
|
|
1366
1572
|
result = xml_text_overlap_lint.lint_xml(
|
|
1367
1573
|
"""
|
|
1368
|
-
<slide xmlns="
|
|
1574
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1369
1575
|
<data>
|
|
1370
1576
|
<shape id="just-warning" type="text" topLeftX="80" topLeftY="80" width="360" height="50">
|
|
1371
1577
|
<content fontSize="20" lineSpacing="fixed:20" autoFit="no-auto-fit">
|
|
@@ -1392,7 +1598,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1392
1598
|
def test_lint_xml_text_may_overflow_shape_downgrades_background_decoration_to_info(self) -> None:
|
|
1393
1599
|
result = xml_text_overlap_lint.lint_xml(
|
|
1394
1600
|
"""
|
|
1395
|
-
<slide xmlns="
|
|
1601
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1396
1602
|
<data>
|
|
1397
1603
|
<shape id="bg-deco" type="text" topLeftX="0" topLeftY="0" width="600" height="80" alpha="0.3">
|
|
1398
1604
|
<content fontSize="120" lineSpacing="fixed:120" autoFit="no-auto-fit"><p>2026</p></content>
|
|
@@ -1418,7 +1624,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1418
1624
|
def test_lint_xml_reports_shape_alpha_ghost_text_out_of_canvas_but_allows_overlap(self) -> None:
|
|
1419
1625
|
result = xml_text_overlap_lint.lint_xml(
|
|
1420
1626
|
"""
|
|
1421
|
-
<slide xmlns="
|
|
1627
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1422
1628
|
<data>
|
|
1423
1629
|
<shape id="ghost-number" type="text" topLeftX="-60" topLeftY="30" width="360" height="180" alpha="0.2">
|
|
1424
1630
|
<content fontSize="160" lineSpacing="fixed:160" wrap="false"><p>01</p></content>
|
|
@@ -1438,7 +1644,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1438
1644
|
def test_lint_xml_reports_content_color_alpha_ghost_text_out_of_canvas_but_allows_overlap(self) -> None:
|
|
1439
1645
|
result = xml_text_overlap_lint.lint_xml(
|
|
1440
1646
|
"""
|
|
1441
|
-
<slide xmlns="
|
|
1647
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1442
1648
|
<data>
|
|
1443
1649
|
<shape id="ghost-year" type="text" topLeftX="760" topLeftY="20" width="260" height="160">
|
|
1444
1650
|
<content fontSize="140" color="rgba(0,0,0,0.2)" lineSpacing="fixed:140" wrap="false"><p>2026</p></content>
|
|
@@ -1458,7 +1664,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1458
1664
|
def test_lint_xml_reports_faint_medium_ghost_text_out_of_canvas_but_allows_overlap(self) -> None:
|
|
1459
1665
|
result = xml_text_overlap_lint.lint_xml(
|
|
1460
1666
|
"""
|
|
1461
|
-
<slide xmlns="
|
|
1667
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1462
1668
|
<data>
|
|
1463
1669
|
<shape id="medium-ghost" type="text" topLeftX="820" topLeftY="300" width="270" height="72" alpha="0.32">
|
|
1464
1670
|
<content fontSize="40" lineSpacing="fixed:40" wrap="false"><p>OFF EDGE</p></content>
|
|
@@ -1478,7 +1684,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1478
1684
|
def test_lint_xml_allows_ghost_text_image_overlap(self) -> None:
|
|
1479
1685
|
result = xml_text_overlap_lint.lint_xml(
|
|
1480
1686
|
"""
|
|
1481
|
-
<slide xmlns="
|
|
1687
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1482
1688
|
<data>
|
|
1483
1689
|
<shape id="ghost-label" type="text" topLeftX="100" topLeftY="40" width="560" height="160" alpha="0.2">
|
|
1484
1690
|
<content fontSize="120" lineSpacing="fixed:120" wrap="false"><p>2026</p></content>
|
|
@@ -1498,7 +1704,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1498
1704
|
def test_lint_slide_allows_ghost_text_whiteboard_overlap(self) -> None:
|
|
1499
1705
|
result = xml_text_overlap_lint.lint_slide(
|
|
1500
1706
|
"""
|
|
1501
|
-
<slide xmlns="
|
|
1707
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1502
1708
|
<data>
|
|
1503
1709
|
<whiteboard id="board" topLeftX="180" topLeftY="70" width="420" height="300"/>
|
|
1504
1710
|
<shape id="ghost-label" type="text" topLeftX="100" topLeftY="40" width="560" height="160" alpha="0.2">
|
|
@@ -1518,7 +1724,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1518
1724
|
def test_lint_xml_reports_faint_ghost_text_out_of_canvas_without_area_threshold(self) -> None:
|
|
1519
1725
|
result = xml_text_overlap_lint.lint_xml(
|
|
1520
1726
|
"""
|
|
1521
|
-
<slide xmlns="
|
|
1727
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1522
1728
|
<data>
|
|
1523
1729
|
<shape id="small-ghost" type="text" topLeftX="940" topLeftY="300" width="40" height="40" alpha="0.32">
|
|
1524
1730
|
<content fontSize="36" lineSpacing="fixed:36" wrap="false"><p>土</p></content>
|
|
@@ -1533,7 +1739,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1533
1739
|
def test_lint_xml_keeps_out_of_canvas_error_for_medium_text_without_faint_alpha(self) -> None:
|
|
1534
1740
|
result = xml_text_overlap_lint.lint_xml(
|
|
1535
1741
|
"""
|
|
1536
|
-
<slide xmlns="
|
|
1742
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1537
1743
|
<data>
|
|
1538
1744
|
<shape id="medium-not-ghost" type="text" topLeftX="820" topLeftY="300" width="270" height="72" alpha="0.36">
|
|
1539
1745
|
<content fontSize="54" lineSpacing="fixed:54" wrap="false"><p>OFF EDGE</p></content>
|
|
@@ -1549,7 +1755,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1549
1755
|
def test_lint_xml_keeps_out_of_canvas_error_for_half_alpha_large_text(self) -> None:
|
|
1550
1756
|
result = xml_text_overlap_lint.lint_xml(
|
|
1551
1757
|
"""
|
|
1552
|
-
<slide xmlns="
|
|
1758
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1553
1759
|
<data>
|
|
1554
1760
|
<shape id="half-alpha" type="text" topLeftX="760" topLeftY="20" width="260" height="160">
|
|
1555
1761
|
<content fontSize="140" color="rgba(0,0,0,0.5)" lineSpacing="fixed:140" wrap="false"><p>2026</p></content>
|
|
@@ -1565,7 +1771,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1565
1771
|
def test_lint_xml_text_may_overflow_shape_keeps_error_when_alpha_not_low(self) -> None:
|
|
1566
1772
|
result = xml_text_overlap_lint.lint_xml(
|
|
1567
1773
|
"""
|
|
1568
|
-
<slide xmlns="
|
|
1774
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1569
1775
|
<data>
|
|
1570
1776
|
<shape id="opaque-big" type="text" topLeftX="0" topLeftY="0" width="600" height="80" alpha="0.9">
|
|
1571
1777
|
<content fontSize="120" lineSpacing="fixed:120" autoFit="no-auto-fit"><p>2026</p></content>
|
|
@@ -1587,7 +1793,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1587
1793
|
def test_lint_xml_text_may_overflow_shape_keeps_error_when_no_foreground_text(self) -> None:
|
|
1588
1794
|
result = xml_text_overlap_lint.lint_xml(
|
|
1589
1795
|
"""
|
|
1590
|
-
<slide xmlns="
|
|
1796
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1591
1797
|
<data>
|
|
1592
1798
|
<shape id="lonely-big" type="text" topLeftX="0" topLeftY="0" width="600" height="80" alpha="0.3">
|
|
1593
1799
|
<content fontSize="120" lineSpacing="fixed:120" autoFit="no-auto-fit"><p>2026</p></content>
|
|
@@ -1606,7 +1812,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1606
1812
|
def test_lint_xml_text_may_overflow_shape_keeps_error_when_foreground_alpha_zero(self) -> None:
|
|
1607
1813
|
result = xml_text_overlap_lint.lint_xml(
|
|
1608
1814
|
"""
|
|
1609
|
-
<slide xmlns="
|
|
1815
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1610
1816
|
<data>
|
|
1611
1817
|
<shape id="bg-deco" type="text" topLeftX="0" topLeftY="0" width="600" height="80" alpha="0.3">
|
|
1612
1818
|
<content fontSize="120" lineSpacing="fixed:120" autoFit="no-auto-fit"><p>2026</p></content>
|
|
@@ -1628,7 +1834,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1628
1834
|
def test_lint_xml_text_may_overflow_shape_keeps_error_when_foreground_is_below_in_order(self) -> None:
|
|
1629
1835
|
result = xml_text_overlap_lint.lint_xml(
|
|
1630
1836
|
"""
|
|
1631
|
-
<slide xmlns="
|
|
1837
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1632
1838
|
<data>
|
|
1633
1839
|
<shape id="foreground" type="text" topLeftX="40" topLeftY="20" width="400" height="60">
|
|
1634
1840
|
<content fontSize="20" lineSpacing="fixed:24"><p>Annual Report</p></content>
|
|
@@ -1650,7 +1856,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1650
1856
|
def test_lint_xml_uses_paragraph_spacing_overrides_for_text_height_warning(self) -> None:
|
|
1651
1857
|
result = xml_text_overlap_lint.lint_xml(
|
|
1652
1858
|
"""
|
|
1653
|
-
<slide xmlns="
|
|
1859
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1654
1860
|
<data>
|
|
1655
1861
|
<shape id="paragraph-overflow" type="text" topLeftX="80" topLeftY="80" width="360" height="30">
|
|
1656
1862
|
<content fontSize="20" lineSpacing="multiple:1.5" autoFit="no-auto-fit">
|
|
@@ -1677,7 +1883,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1677
1883
|
def test_lint_xml_uses_letter_spacing_for_text_overflow_warning(self) -> None:
|
|
1678
1884
|
result = xml_text_overlap_lint.lint_xml(
|
|
1679
1885
|
"""
|
|
1680
|
-
<slide xmlns="
|
|
1886
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1681
1887
|
<data>
|
|
1682
1888
|
<shape id="baseline" type="text" topLeftX="0" topLeftY="0" width="120" height="30">
|
|
1683
1889
|
<content fontSize="20" lineSpacing="multiple:1.5" autoFit="no-auto-fit"><p>一二三四五六</p></content>
|
|
@@ -1712,8 +1918,8 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1712
1918
|
def test_lint_xml_allows_template_style_images_outside_canvas(self) -> None:
|
|
1713
1919
|
result = xml_text_overlap_lint.lint_xml(
|
|
1714
1920
|
"""
|
|
1715
|
-
<presentation xmlns="
|
|
1716
|
-
<slide xmlns="
|
|
1921
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
1922
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1717
1923
|
<data>
|
|
1718
1924
|
<img src="tok" topLeftX="-120" topLeftY="20" width="360" height="360"/>
|
|
1719
1925
|
<shape type="text" topLeftX="40" topLeftY="80" width="180" height="80">
|
|
@@ -1733,7 +1939,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1733
1939
|
def test_extract_elements_preserves_supported_element_geometry_order_and_text_metadata(self) -> None:
|
|
1734
1940
|
elements = xml_text_overlap_lint.extract_elements(
|
|
1735
1941
|
"""
|
|
1736
|
-
<slide xmlns="
|
|
1942
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1737
1943
|
<data>
|
|
1738
1944
|
<img id="photo" src="tok" topLeftX="10" topLeftY="20" width="100" height="80"/>
|
|
1739
1945
|
<shape id="headline" type="text" topLeftX="40" topLeftY="60" width="320" height="90">
|
|
@@ -1745,6 +1951,9 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1745
1951
|
<table id="table" topLeftX="400" topLeftY="60" width="220" height="120"></table>
|
|
1746
1952
|
<chart id="chart" topLeftX="640" topLeftY="60" width="220" height="120"/>
|
|
1747
1953
|
<whiteboard id="wb" topLeftX="80" topLeftY="220" width="760" height="240"/>
|
|
1954
|
+
<embed id="emb" topLeftX="600" topLeftY="320" width="240" height="140">
|
|
1955
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 240 140"><rect x="0" y="0" width="240" height="140"/></svg>
|
|
1956
|
+
</embed>
|
|
1748
1957
|
<shape id="missing-height" type="text" topLeftX="80" topLeftY="480" width="320">
|
|
1749
1958
|
<content><p>Skipped</p></content>
|
|
1750
1959
|
</shape>
|
|
@@ -1752,9 +1961,9 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1752
1961
|
</slide>
|
|
1753
1962
|
"""
|
|
1754
1963
|
)
|
|
1755
|
-
self.assertEqual([element["id"] for element in elements], ["photo", "headline", "table", "chart", "wb"])
|
|
1756
|
-
self.assertEqual([element["kind"] for element in elements], ["img", "shape", "table", "chart", "whiteboard"])
|
|
1757
|
-
self.assertEqual([element["order"] for element in elements], [0, 1, 2, 3, 4])
|
|
1964
|
+
self.assertEqual([element["id"] for element in elements], ["photo", "headline", "table", "chart", "wb", "emb"])
|
|
1965
|
+
self.assertEqual([element["kind"] for element in elements], ["img", "shape", "table", "chart", "whiteboard", "embed"])
|
|
1966
|
+
self.assertEqual([element["order"] for element in elements], [0, 1, 2, 3, 4, 5])
|
|
1758
1967
|
self.assertEqual(elements[1]["type"], "text")
|
|
1759
1968
|
self.assertEqual(elements[1]["textType"], "headline")
|
|
1760
1969
|
self.assertEqual(elements[1]["textAlign"], "center")
|
|
@@ -1765,8 +1974,8 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1765
1974
|
def test_lint_xml_ignores_small_out_of_bounds_images(self) -> None:
|
|
1766
1975
|
result = xml_text_overlap_lint.lint_xml(
|
|
1767
1976
|
"""
|
|
1768
|
-
<presentation xmlns="
|
|
1769
|
-
<slide xmlns="
|
|
1977
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
1978
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1770
1979
|
<data>
|
|
1771
1980
|
<img src="tok" topLeftX="-20" topLeftY="20" width="120" height="120"/>
|
|
1772
1981
|
</data>
|
|
@@ -1779,8 +1988,8 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1779
1988
|
def test_lint_xml_ignores_out_of_canvas_images(self) -> None:
|
|
1780
1989
|
result = xml_text_overlap_lint.lint_xml(
|
|
1781
1990
|
"""
|
|
1782
|
-
<presentation xmlns="
|
|
1783
|
-
<slide xmlns="
|
|
1991
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
1992
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1784
1993
|
<data>
|
|
1785
1994
|
<img src="right" topLeftX="780" topLeftY="0" width="500" height="540"/>
|
|
1786
1995
|
<img src="bottom" topLeftX="0" topLeftY="430" width="900" height="280"/>
|
|
@@ -1794,8 +2003,8 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1794
2003
|
def test_lint_xml_ignores_full_bleed_images_outside_canvas(self) -> None:
|
|
1795
2004
|
result = xml_text_overlap_lint.lint_xml(
|
|
1796
2005
|
"""
|
|
1797
|
-
<presentation xmlns="
|
|
1798
|
-
<slide xmlns="
|
|
2006
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
2007
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1799
2008
|
<data>
|
|
1800
2009
|
<img src="tok" topLeftX="-80" topLeftY="-20" width="1080" height="600"/>
|
|
1801
2010
|
</data>
|
|
@@ -1808,8 +2017,8 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1808
2017
|
def test_lint_xml_reports_text_and_chart_but_not_image_out_of_canvas(self) -> None:
|
|
1809
2018
|
result = xml_text_overlap_lint.lint_xml(
|
|
1810
2019
|
"""
|
|
1811
|
-
<presentation xmlns="
|
|
1812
|
-
<slide xmlns="
|
|
2020
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
2021
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1813
2022
|
<data>
|
|
1814
2023
|
<shape id="outside-shape" type="text" topLeftX="-10" topLeftY="40" width="50" height="50"/>
|
|
1815
2024
|
<img id="outside-img" src="token" topLeftX="120" topLeftY="-20" width="50" height="50"/>
|
|
@@ -1838,7 +2047,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1838
2047
|
def test_lint_xml_ignores_line_out_of_canvas(self) -> None:
|
|
1839
2048
|
result = xml_text_overlap_lint.lint_xml(
|
|
1840
2049
|
"""
|
|
1841
|
-
<slide xmlns="
|
|
2050
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1842
2051
|
<data>
|
|
1843
2052
|
<shape id="body" type="text" topLeftX="80" topLeftY="80" width="300" height="60">
|
|
1844
2053
|
<content fontSize="18"><p>Visible content</p></content>
|
|
@@ -1855,7 +2064,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1855
2064
|
def test_lint_xml_reports_horizontal_line_crossing_headline_glyphs(self) -> None:
|
|
1856
2065
|
result = xml_text_overlap_lint.lint_xml(
|
|
1857
2066
|
"""
|
|
1858
|
-
<slide xmlns="
|
|
2067
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1859
2068
|
<data>
|
|
1860
2069
|
<shape id="title" type="text" topLeftX="80" topLeftY="200" width="500" height="90">
|
|
1861
2070
|
<content fontSize="60"><p>测试文字 ABC</p></content>
|
|
@@ -1876,7 +2085,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1876
2085
|
def test_lint_xml_reports_vertical_line_crossing_multiline_text(self) -> None:
|
|
1877
2086
|
result = xml_text_overlap_lint.lint_xml(
|
|
1878
2087
|
"""
|
|
1879
|
-
<slide xmlns="
|
|
2088
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1880
2089
|
<data>
|
|
1881
2090
|
<shape id="col" type="text" topLeftX="700" topLeftY="180" width="240" height="180">
|
|
1882
2091
|
<content fontSize="20"><p>第一行文字内容</p><p>第二行文字内容</p><p>第三行文字内容</p></content>
|
|
@@ -1896,7 +2105,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1896
2105
|
def test_lint_xml_reports_diagonal_line_crossing_text_block(self) -> None:
|
|
1897
2106
|
result = xml_text_overlap_lint.lint_xml(
|
|
1898
2107
|
"""
|
|
1899
|
-
<slide xmlns="
|
|
2108
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1900
2109
|
<data>
|
|
1901
2110
|
<shape id="para" type="text" topLeftX="80" topLeftY="400" width="420" height="140">
|
|
1902
2111
|
<content fontSize="18"><p>这是一段测试文字用于验证线条穿过</p></content>
|
|
@@ -1918,7 +2127,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1918
2127
|
# through empty space in the opposite corner -- a naive bbox test would false-positive here.
|
|
1919
2128
|
result = xml_text_overlap_lint.lint_xml(
|
|
1920
2129
|
"""
|
|
1921
|
-
<slide xmlns="
|
|
2130
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1922
2131
|
<data>
|
|
1923
2132
|
<shape id="corner-text" type="text" topLeftX="80" topLeftY="80" width="120" height="40">
|
|
1924
2133
|
<content fontSize="18"><p>corner</p></content>
|
|
@@ -1938,7 +2147,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1938
2147
|
def test_lint_xml_ignores_line_touching_text_frame_but_not_glyphs(self) -> None:
|
|
1939
2148
|
result = xml_text_overlap_lint.lint_xml(
|
|
1940
2149
|
"""
|
|
1941
|
-
<slide xmlns="
|
|
2150
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1942
2151
|
<data>
|
|
1943
2152
|
<shape id="lbl" type="text" topLeftX="80" topLeftY="80" width="300" height="200">
|
|
1944
2153
|
<content fontSize="18" verticalAlign="top"><p>短标签</p></content>
|
|
@@ -1955,7 +2164,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1955
2164
|
def test_lint_xml_ignores_invisible_line_crossing_text(self) -> None:
|
|
1956
2165
|
result = xml_text_overlap_lint.lint_xml(
|
|
1957
2166
|
"""
|
|
1958
|
-
<slide xmlns="
|
|
2167
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1959
2168
|
<data>
|
|
1960
2169
|
<shape id="title" type="text" topLeftX="80" topLeftY="200" width="500" height="90">
|
|
1961
2170
|
<content fontSize="60"><p>测试文字 ABC</p></content>
|
|
@@ -1974,7 +2183,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1974
2183
|
# frame's left edge renders before the first glyph, so it must not be flagged.
|
|
1975
2184
|
result = xml_text_overlap_lint.lint_xml(
|
|
1976
2185
|
"""
|
|
1977
|
-
<slide xmlns="
|
|
2186
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1978
2187
|
<data>
|
|
1979
2188
|
<shape width="240" height="60" topLeftX="120" topLeftY="100" type="text" id="bmm">
|
|
1980
2189
|
<content fontSize="20" fontFamily="Arial" color="rgba(31, 35, 41, 1)" lineSpacing="fixed:24">
|
|
@@ -1995,7 +2204,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
1995
2204
|
# <line> only, so a <polyline> over text is not flagged.
|
|
1996
2205
|
result = xml_text_overlap_lint.lint_xml(
|
|
1997
2206
|
"""
|
|
1998
|
-
<slide xmlns="
|
|
2207
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
1999
2208
|
<data>
|
|
2000
2209
|
<shape width="240" height="60" topLeftX="120" topLeftY="100" type="text" id="bmr">
|
|
2001
2210
|
<content fontSize="20" fontFamily="Arial" color="rgba(31, 35, 41, 1)" lineSpacing="fixed:24">
|
|
@@ -2017,7 +2226,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
2017
2226
|
# under the visual glyph box (underline look) and must not be flagged.
|
|
2018
2227
|
result = xml_text_overlap_lint.lint_xml(
|
|
2019
2228
|
"""
|
|
2020
|
-
<slide xmlns="
|
|
2229
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2021
2230
|
<data>
|
|
2022
2231
|
<shape width="240" height="80" topLeftX="120" topLeftY="100" type="text" id="bmB">
|
|
2023
2232
|
<content fontSize="20" fontFamily="Arial" color="rgba(31, 35, 41, 1)" lineSpacing="fixed:24">
|
|
@@ -2036,8 +2245,8 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
2036
2245
|
def test_lint_xml_uses_rotated_text_and_chart_bounds_for_canvas_validation(self) -> None:
|
|
2037
2246
|
result = xml_text_overlap_lint.lint_xml(
|
|
2038
2247
|
"""
|
|
2039
|
-
<presentation xmlns="
|
|
2040
|
-
<slide xmlns="
|
|
2248
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
2249
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2041
2250
|
<data>
|
|
2042
2251
|
<shape id="rotated-text" type="text" topLeftX="0" topLeftY="0" width="100" height="100" rotation="45"/>
|
|
2043
2252
|
<chart id="rotated-chart" topLeftX="860" topLeftY="200" width="100" height="100" rotation="45">
|
|
@@ -2063,8 +2272,8 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
2063
2272
|
def test_lint_xml_uses_declared_bounds_for_rect_and_ignores_images(self) -> None:
|
|
2064
2273
|
result = xml_text_overlap_lint.lint_xml(
|
|
2065
2274
|
"""
|
|
2066
|
-
<presentation xmlns="
|
|
2067
|
-
<slide xmlns="
|
|
2275
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
2276
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2068
2277
|
<data>
|
|
2069
2278
|
<shape id="rotated-rect" type="rect" topLeftX="900" topLeftY="0" width="100" height="100" rotation="45"/>
|
|
2070
2279
|
<img id="rotated-image" src="token" topLeftX="860" topLeftY="200" width="100" height="100" rotation="45"/>
|
|
@@ -2126,8 +2335,8 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
2126
2335
|
def test_lint_xml_rejects_non_finite_rotation_values_from_xsd(self) -> None:
|
|
2127
2336
|
result = xml_text_overlap_lint.lint_xml(
|
|
2128
2337
|
"""
|
|
2129
|
-
<presentation xmlns="
|
|
2130
|
-
<slide xmlns="
|
|
2338
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
2339
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2131
2340
|
<data>
|
|
2132
2341
|
<shape id="infinite" type="text" topLeftX="-10" topLeftY="0" width="20" height="20" rotation="inf"/>
|
|
2133
2342
|
<shape id="negative-infinite" type="text" topLeftX="0" topLeftY="-10" width="20" height="20" rotation="-inf"/>
|
|
@@ -2151,8 +2360,8 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
2151
2360
|
def test_lint_xml_reports_table_bottom_overflow_from_declared_bounds(self) -> None:
|
|
2152
2361
|
result = xml_text_overlap_lint.lint_xml(
|
|
2153
2362
|
"""
|
|
2154
|
-
<presentation xmlns="
|
|
2155
|
-
<slide xmlns="
|
|
2363
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
2364
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2156
2365
|
<data>
|
|
2157
2366
|
<table id="score-table" topLeftX="54" topLeftY="238" width="414" height="385">
|
|
2158
2367
|
<tr><td><content><p>Score</p></content></td></tr>
|
|
@@ -2172,8 +2381,8 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
2172
2381
|
def test_lint_xml_reports_table_right_overflow_from_declared_bounds(self) -> None:
|
|
2173
2382
|
result = xml_text_overlap_lint.lint_xml(
|
|
2174
2383
|
"""
|
|
2175
|
-
<presentation xmlns="
|
|
2176
|
-
<slide xmlns="
|
|
2384
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
2385
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2177
2386
|
<data>
|
|
2178
2387
|
<table id="wide-table" topLeftX="850" topLeftY="80" width="180" height="120">
|
|
2179
2388
|
<tr><td><content><p>Score</p></content></td></tr>
|
|
@@ -2191,8 +2400,8 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
2191
2400
|
def test_lint_xml_allows_table_with_declared_bounds_inside_canvas(self) -> None:
|
|
2192
2401
|
result = xml_text_overlap_lint.lint_xml(
|
|
2193
2402
|
"""
|
|
2194
|
-
<presentation xmlns="
|
|
2195
|
-
<slide xmlns="
|
|
2403
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
2404
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2196
2405
|
<data>
|
|
2197
2406
|
<table id="inside-table" topLeftX="40" topLeftY="120" width="880" height="360">
|
|
2198
2407
|
<tr><td><content><p>Score</p></content></td></tr>
|
|
@@ -2208,8 +2417,8 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
2208
2417
|
def test_lint_xml_reports_resolved_table_bounds_when_declared_sizes_are_missing(self) -> None:
|
|
2209
2418
|
result = xml_text_overlap_lint.lint_xml(
|
|
2210
2419
|
"""
|
|
2211
|
-
<presentation xmlns="
|
|
2212
|
-
<slide xmlns="
|
|
2420
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
2421
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2213
2422
|
<data>
|
|
2214
2423
|
<table id="implicit-size-table" topLeftX="850" topLeftY="480">
|
|
2215
2424
|
<colgroup><col/><col/></colgroup>
|
|
@@ -2227,76 +2436,635 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
2227
2436
|
self.assertEqual(issue["bbox"], {"x": 850, "y": 480, "width": 220, "height": 74})
|
|
2228
2437
|
self.assertEqual(issue["overflow"], {"left": 0, "top": 0, "right": 110, "bottom": 14})
|
|
2229
2438
|
|
|
2230
|
-
def
|
|
2439
|
+
def test_lint_xml_xml_path_preserves_source_index_after_filtered_table(self) -> None:
|
|
2231
2440
|
result = xml_text_overlap_lint.lint_xml(
|
|
2232
2441
|
"""
|
|
2233
|
-
<
|
|
2234
|
-
<
|
|
2235
|
-
<
|
|
2236
|
-
<
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
</
|
|
2241
|
-
</
|
|
2242
|
-
</
|
|
2442
|
+
<slide xmlns="http://www.larkoffice.com/sml/2.0">
|
|
2443
|
+
<data>
|
|
2444
|
+
<table id="t1" topLeftX="20" topLeftY="20">
|
|
2445
|
+
<tr><td/></tr>
|
|
2446
|
+
</table>
|
|
2447
|
+
<table id="t2" topLeftX="20" topLeftY="100" width="9999" height="100">
|
|
2448
|
+
<tr><td/></tr>
|
|
2449
|
+
</table>
|
|
2450
|
+
</data>
|
|
2451
|
+
</slide>
|
|
2243
2452
|
"""
|
|
2244
2453
|
)
|
|
2245
|
-
issues = result["slides"][0]["issues"]
|
|
2246
|
-
canvas_issue = next(issue for issue in issues if issue["code"] == "table_out_of_canvas")
|
|
2247
|
-
mismatch_issue = next(issue for issue in issues if issue["code"] == "table_resolved_size_mismatch")
|
|
2248
|
-
self.assertEqual(result["summary"]["error_count"], 1)
|
|
2249
|
-
self.assertEqual(canvas_issue["bbox"], {"x": 800, "y": 80, "width": 200, "height": 40})
|
|
2250
|
-
self.assertEqual(canvas_issue["overflow"]["right"], 40)
|
|
2251
|
-
self.assertEqual(mismatch_issue["dimension"], "width")
|
|
2252
|
-
self.assertEqual(mismatch_issue["resolved_size"], canvas_issue["bbox"]["width"])
|
|
2253
2454
|
|
|
2254
|
-
|
|
2455
|
+
issue = next(
|
|
2456
|
+
issue
|
|
2457
|
+
for issue in result["slides"][0]["issues"]
|
|
2458
|
+
if issue["code"] == "table_out_of_canvas"
|
|
2459
|
+
)
|
|
2460
|
+
self.assertEqual(issue["element_ids"], ["t2"])
|
|
2461
|
+
self.assertEqual(
|
|
2462
|
+
issue["related_objects"][0]["xml_path"],
|
|
2463
|
+
"slide[1]/data/table[2]",
|
|
2464
|
+
)
|
|
2465
|
+
|
|
2466
|
+
def test_lint_xml_duplicate_id_keeps_issue_bound_to_original_shape(self) -> None:
|
|
2255
2467
|
result = xml_text_overlap_lint.lint_xml(
|
|
2256
2468
|
"""
|
|
2257
|
-
<
|
|
2258
|
-
<
|
|
2259
|
-
<
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
<colgroup><col width="100"/><col width="100"/></colgroup>
|
|
2264
|
-
<tr height="40"><td/><td/></tr>
|
|
2265
|
-
</table>
|
|
2266
|
-
</data>
|
|
2267
|
-
</slide>
|
|
2268
|
-
</presentation>
|
|
2469
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2470
|
+
<data>
|
|
2471
|
+
<shape id="dup" type="rect" topLeftX="-20" topLeftY="40" width="50" height="50"/>
|
|
2472
|
+
<shape id="dup" type="rect" topLeftX="100" topLeftY="40" width="50" height="50"/>
|
|
2473
|
+
</data>
|
|
2474
|
+
</slide>
|
|
2269
2475
|
"""
|
|
2270
2476
|
)
|
|
2271
|
-
issues = result["slides"][0]["issues"]
|
|
2272
|
-
canvas_issue = next(issue for issue in issues if issue["code"] == "table_out_of_canvas")
|
|
2273
|
-
mismatch_issue = next(issue for issue in issues if issue["code"] == "table_resolved_size_mismatch")
|
|
2274
|
-
self.assertEqual(canvas_issue["elements"], ["table-3"])
|
|
2275
|
-
self.assertEqual(mismatch_issue["elements"], ["table-3"])
|
|
2276
2477
|
|
|
2277
|
-
|
|
2478
|
+
canvas_issue = next(
|
|
2479
|
+
issue for issue in result["slides"][0]["issues"]
|
|
2480
|
+
if issue["code"] == "shape_out_of_canvas"
|
|
2481
|
+
)
|
|
2482
|
+
self.assertEqual(canvas_issue["element_ids"], ["dup"])
|
|
2483
|
+
self.assertEqual(
|
|
2484
|
+
canvas_issue["related_objects"],
|
|
2485
|
+
[
|
|
2486
|
+
{
|
|
2487
|
+
"element_id": "dup",
|
|
2488
|
+
"kind": "shape",
|
|
2489
|
+
"type": "rect",
|
|
2490
|
+
"bbox": {"x": -20, "y": 40, "width": 50, "height": 50},
|
|
2491
|
+
"xml_path": "slide[1]/data/shape[1]",
|
|
2492
|
+
}
|
|
2493
|
+
],
|
|
2494
|
+
)
|
|
2495
|
+
self.assertTrue(
|
|
2496
|
+
canvas_issue["hint"].startswith(
|
|
2497
|
+
"Locate via related_objects[].xml_path. "
|
|
2498
|
+
)
|
|
2499
|
+
)
|
|
2500
|
+
duplicate_issue = next(
|
|
2501
|
+
issue for issue in result["slides"][0]["issues"]
|
|
2502
|
+
if issue["code"] == "duplicate_element_id"
|
|
2503
|
+
)
|
|
2504
|
+
self.assertEqual(
|
|
2505
|
+
duplicate_issue["hint"],
|
|
2506
|
+
"Locate via related_objects[].xml_path. "
|
|
2507
|
+
"Do not invent replacement IDs. For newly authored elements, remove the id attribute. "
|
|
2508
|
+
"When updating read-back XML, keep the server ID on the original element only and remove it "
|
|
2509
|
+
"from copied or new elements.",
|
|
2510
|
+
)
|
|
2511
|
+
self.assertEqual(duplicate_issue["element_ids"], ["dup", "dup"])
|
|
2512
|
+
self.assertEqual(
|
|
2513
|
+
[obj["xml_path"] for obj in duplicate_issue["related_objects"]],
|
|
2514
|
+
["slide[1]/data/shape[1]", "slide[1]/data/shape[2]"],
|
|
2515
|
+
)
|
|
2516
|
+
|
|
2517
|
+
def test_lint_xml_blocks_duplicate_table_cell_ids(self) -> None:
|
|
2278
2518
|
result = xml_text_overlap_lint.lint_xml(
|
|
2279
2519
|
"""
|
|
2280
|
-
<
|
|
2281
|
-
<
|
|
2282
|
-
<
|
|
2283
|
-
<
|
|
2284
|
-
|
|
2285
|
-
<
|
|
2286
|
-
<
|
|
2287
|
-
</
|
|
2288
|
-
</
|
|
2289
|
-
</
|
|
2290
|
-
</
|
|
2520
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2521
|
+
<data>
|
|
2522
|
+
<table id="table-1" topLeftX="80" topLeftY="80" width="800" height="120">
|
|
2523
|
+
<colgroup><col width="400"/><col width="400"/></colgroup>
|
|
2524
|
+
<tr height="120">
|
|
2525
|
+
<td id="bjs"><content fontSize="24"><p>Original cell</p></content></td>
|
|
2526
|
+
<td id="bjs"><content fontSize="24"><p>Copied cell</p></content></td>
|
|
2527
|
+
</tr>
|
|
2528
|
+
</table>
|
|
2529
|
+
</data>
|
|
2530
|
+
</slide>
|
|
2291
2531
|
"""
|
|
2292
2532
|
)
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
self.
|
|
2533
|
+
|
|
2534
|
+
issue = next(
|
|
2535
|
+
issue
|
|
2536
|
+
for issue in result["slides"][0]["issues"]
|
|
2537
|
+
if issue["code"] == "duplicate_element_id"
|
|
2538
|
+
)
|
|
2539
|
+
self.assertFalse(result["summary"]["release_ready"])
|
|
2540
|
+
self.assertEqual(issue["element_ids"], ["bjs", "bjs"])
|
|
2541
|
+
self.assertEqual(
|
|
2542
|
+
issue["related_objects"],
|
|
2543
|
+
[
|
|
2544
|
+
{
|
|
2545
|
+
"element_id": "bjs",
|
|
2546
|
+
"kind": "td",
|
|
2547
|
+
"type": "td",
|
|
2548
|
+
"xml_path": "slide[1]/data/table[1]/tr[1]/td[1]",
|
|
2549
|
+
},
|
|
2550
|
+
{
|
|
2551
|
+
"element_id": "bjs",
|
|
2552
|
+
"kind": "td",
|
|
2553
|
+
"type": "td",
|
|
2554
|
+
"xml_path": "slide[1]/data/table[1]/tr[1]/td[2]",
|
|
2555
|
+
},
|
|
2556
|
+
],
|
|
2557
|
+
)
|
|
2558
|
+
|
|
2559
|
+
def test_lint_xml_blocks_duplicate_id_shared_by_shape_and_table_cell(self) -> None:
|
|
2560
|
+
result = xml_text_overlap_lint.lint_xml(
|
|
2561
|
+
"""
|
|
2562
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2563
|
+
<data>
|
|
2564
|
+
<shape id="baa" type="rect" topLeftX="40" topLeftY="40" width="80" height="80"/>
|
|
2565
|
+
<table id="table-1" topLeftX="160" topLeftY="40" width="200" height="80">
|
|
2566
|
+
<tr height="80"><td id="baa"><content fontSize="12"><p>Cell</p></content></td></tr>
|
|
2567
|
+
</table>
|
|
2568
|
+
</data>
|
|
2569
|
+
</slide>
|
|
2570
|
+
"""
|
|
2571
|
+
)
|
|
2572
|
+
|
|
2573
|
+
issue = next(
|
|
2574
|
+
issue
|
|
2575
|
+
for issue in result["slides"][0]["issues"]
|
|
2576
|
+
if issue["code"] == "duplicate_element_id"
|
|
2577
|
+
)
|
|
2578
|
+
self.assertEqual(issue["element_ids"], ["baa", "baa"])
|
|
2579
|
+
self.assertEqual(
|
|
2580
|
+
[obj["xml_path"] for obj in issue["related_objects"]],
|
|
2581
|
+
["slide[1]/data/shape[1]", "slide[1]/data/table[1]/tr[1]/td[1]"],
|
|
2582
|
+
)
|
|
2583
|
+
|
|
2584
|
+
def test_lint_xml_blocks_duplicate_id_shared_by_shape_and_undefined(self) -> None:
|
|
2585
|
+
result = xml_text_overlap_lint.lint_xml(
|
|
2586
|
+
"""
|
|
2587
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2588
|
+
<data>
|
|
2589
|
+
<shape id="dup" type="rect" topLeftX="40" topLeftY="40" width="80" height="80"/>
|
|
2590
|
+
<undefined id="dup" type="video"/>
|
|
2591
|
+
</data>
|
|
2592
|
+
</slide>
|
|
2593
|
+
"""
|
|
2594
|
+
)
|
|
2595
|
+
|
|
2596
|
+
issue = next(
|
|
2597
|
+
issue
|
|
2598
|
+
for issue in result["slides"][0]["issues"]
|
|
2599
|
+
if issue["code"] == "duplicate_element_id"
|
|
2600
|
+
)
|
|
2601
|
+
self.assertFalse(result["summary"]["release_ready"])
|
|
2602
|
+
self.assertEqual(issue["element_ids"], ["dup", "dup"])
|
|
2603
|
+
self.assertEqual(
|
|
2604
|
+
issue["related_objects"],
|
|
2605
|
+
[
|
|
2606
|
+
{
|
|
2607
|
+
"element_id": "dup",
|
|
2608
|
+
"kind": "shape",
|
|
2609
|
+
"type": "rect",
|
|
2610
|
+
"bbox": {"x": 40, "y": 40, "width": 80, "height": 80},
|
|
2611
|
+
"xml_path": "slide[1]/data/shape[1]",
|
|
2612
|
+
},
|
|
2613
|
+
{
|
|
2614
|
+
"element_id": "dup",
|
|
2615
|
+
"kind": "undefined",
|
|
2616
|
+
"type": "video",
|
|
2617
|
+
"xml_path": "slide[1]/data/undefined[1]",
|
|
2618
|
+
},
|
|
2619
|
+
],
|
|
2620
|
+
)
|
|
2621
|
+
|
|
2622
|
+
def test_lint_xml_does_not_report_unique_table_cell_and_note_ids(self) -> None:
|
|
2623
|
+
result = xml_text_overlap_lint.lint_xml(
|
|
2624
|
+
"""
|
|
2625
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2626
|
+
<data>
|
|
2627
|
+
<table id="table-1" topLeftX="80" topLeftY="80" width="800" height="120">
|
|
2628
|
+
<colgroup><col width="400"/><col width="400"/></colgroup>
|
|
2629
|
+
<tr height="120"><td id="baa"/><td id="bab"/></tr>
|
|
2630
|
+
</table>
|
|
2631
|
+
</data>
|
|
2632
|
+
<note id="bac"><content fontSize="12"><p>Note</p></content></note>
|
|
2633
|
+
</slide>
|
|
2634
|
+
"""
|
|
2635
|
+
)
|
|
2636
|
+
|
|
2637
|
+
self.assertNotIn(
|
|
2638
|
+
"duplicate_element_id",
|
|
2639
|
+
[issue["code"] for issue in result["slides"][0]["issues"]],
|
|
2640
|
+
)
|
|
2641
|
+
|
|
2642
|
+
def test_lint_xml_blocks_duplicate_ids_across_slides(self) -> None:
|
|
2643
|
+
result = xml_text_overlap_lint.lint_xml(
|
|
2644
|
+
"""
|
|
2645
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
2646
|
+
<slide>
|
|
2647
|
+
<data>
|
|
2648
|
+
<shape id="dup" type="rect" topLeftX="40" topLeftY="40" width="80" height="80"/>
|
|
2649
|
+
</data>
|
|
2650
|
+
</slide>
|
|
2651
|
+
<slide>
|
|
2652
|
+
<data>
|
|
2653
|
+
<shape id="dup" type="rect" topLeftX="140" topLeftY="40" width="80" height="80"/>
|
|
2654
|
+
</data>
|
|
2655
|
+
</slide>
|
|
2656
|
+
</presentation>
|
|
2657
|
+
"""
|
|
2658
|
+
)
|
|
2659
|
+
|
|
2660
|
+
issue = next(
|
|
2661
|
+
issue
|
|
2662
|
+
for issue in result["document"]["errors"]
|
|
2663
|
+
if issue["code"] == "duplicate_element_id"
|
|
2664
|
+
)
|
|
2665
|
+
self.assertFalse(result["summary"]["release_ready"])
|
|
2666
|
+
self.assertEqual(issue["element_ids"], ["dup", "dup"])
|
|
2667
|
+
self.assertEqual(
|
|
2668
|
+
issue["related_objects"],
|
|
2669
|
+
[
|
|
2670
|
+
{
|
|
2671
|
+
"element_id": "dup",
|
|
2672
|
+
"kind": "shape",
|
|
2673
|
+
"type": "rect",
|
|
2674
|
+
"bbox": {"x": 40, "y": 40, "width": 80, "height": 80},
|
|
2675
|
+
"xml_path": "slide[1]/data/shape[1]",
|
|
2676
|
+
},
|
|
2677
|
+
{
|
|
2678
|
+
"element_id": "dup",
|
|
2679
|
+
"kind": "shape",
|
|
2680
|
+
"type": "rect",
|
|
2681
|
+
"bbox": {"x": 140, "y": 40, "width": 80, "height": 80},
|
|
2682
|
+
"xml_path": "slide[2]/data/shape[1]",
|
|
2683
|
+
},
|
|
2684
|
+
],
|
|
2685
|
+
)
|
|
2686
|
+
|
|
2687
|
+
def test_lint_xml_does_not_treat_slide_ids_as_element_ids(self) -> None:
|
|
2688
|
+
result = xml_text_overlap_lint.lint_xml(
|
|
2689
|
+
"""
|
|
2690
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
2691
|
+
<slide id="dup"><data/></slide>
|
|
2692
|
+
<slide id="dup"><data/></slide>
|
|
2693
|
+
</presentation>
|
|
2694
|
+
"""
|
|
2695
|
+
)
|
|
2696
|
+
|
|
2697
|
+
self.assertNotIn(
|
|
2698
|
+
"duplicate_element_id",
|
|
2699
|
+
[issue["code"] for issue in result["document"]["errors"]],
|
|
2700
|
+
)
|
|
2701
|
+
|
|
2702
|
+
def test_lint_xml_does_not_treat_presentation_id_as_element_id(self) -> None:
|
|
2703
|
+
result = xml_text_overlap_lint.lint_xml(
|
|
2704
|
+
"""
|
|
2705
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" id="dup" width="960" height="540">
|
|
2706
|
+
<slide>
|
|
2707
|
+
<data><undefined id="dup" type="video"/></data>
|
|
2708
|
+
</slide>
|
|
2709
|
+
</presentation>
|
|
2710
|
+
"""
|
|
2711
|
+
)
|
|
2712
|
+
|
|
2713
|
+
self.assertNotIn(
|
|
2714
|
+
"duplicate_element_id",
|
|
2715
|
+
[
|
|
2716
|
+
issue["code"]
|
|
2717
|
+
for issue in [
|
|
2718
|
+
*result["document"]["errors"],
|
|
2719
|
+
*result["slides"][0]["errors"],
|
|
2720
|
+
]
|
|
2721
|
+
],
|
|
2722
|
+
)
|
|
2723
|
+
|
|
2724
|
+
def test_lint_xml_blocks_duplicate_note_ids_across_slides(self) -> None:
|
|
2725
|
+
result = xml_text_overlap_lint.lint_xml(
|
|
2726
|
+
"""
|
|
2727
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
2728
|
+
<slide>
|
|
2729
|
+
<note id="baa"><content fontSize="12"><p>First note</p></content></note>
|
|
2730
|
+
</slide>
|
|
2731
|
+
<slide>
|
|
2732
|
+
<note id="baa"><content fontSize="12"><p>Copied note</p></content></note>
|
|
2733
|
+
</slide>
|
|
2734
|
+
</presentation>
|
|
2735
|
+
"""
|
|
2736
|
+
)
|
|
2737
|
+
|
|
2738
|
+
issue = next(
|
|
2739
|
+
issue
|
|
2740
|
+
for issue in result["document"]["errors"]
|
|
2741
|
+
if issue["code"] == "duplicate_element_id"
|
|
2742
|
+
)
|
|
2743
|
+
self.assertFalse(result["summary"]["release_ready"])
|
|
2744
|
+
self.assertEqual(issue["element_ids"], ["baa", "baa"])
|
|
2745
|
+
self.assertEqual(
|
|
2746
|
+
issue["related_objects"],
|
|
2747
|
+
[
|
|
2748
|
+
{
|
|
2749
|
+
"element_id": "baa",
|
|
2750
|
+
"kind": "note",
|
|
2751
|
+
"type": "note",
|
|
2752
|
+
"xml_path": "slide[1]/note[1]",
|
|
2753
|
+
},
|
|
2754
|
+
{
|
|
2755
|
+
"element_id": "baa",
|
|
2756
|
+
"kind": "note",
|
|
2757
|
+
"type": "note",
|
|
2758
|
+
"xml_path": "slide[2]/note[1]",
|
|
2759
|
+
},
|
|
2760
|
+
],
|
|
2761
|
+
)
|
|
2762
|
+
|
|
2763
|
+
def test_lint_xml_cross_kind_duplicate_id_does_not_change_related_object_kind(self) -> None:
|
|
2764
|
+
result = xml_text_overlap_lint.lint_xml(
|
|
2765
|
+
"""
|
|
2766
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2767
|
+
<data>
|
|
2768
|
+
<shape id="dup" type="rect" topLeftX="-20" topLeftY="40" width="50" height="50"/>
|
|
2769
|
+
<img id="dup" src="token" topLeftX="100" topLeftY="40" width="50" height="50"/>
|
|
2770
|
+
</data>
|
|
2771
|
+
</slide>
|
|
2772
|
+
"""
|
|
2773
|
+
)
|
|
2774
|
+
|
|
2775
|
+
issue = next(
|
|
2776
|
+
issue for issue in result["slides"][0]["issues"]
|
|
2777
|
+
if issue["code"] == "shape_out_of_canvas"
|
|
2778
|
+
)
|
|
2779
|
+
self.assertEqual(issue["related_objects"][0]["kind"], "shape")
|
|
2780
|
+
self.assertEqual(
|
|
2781
|
+
issue["related_objects"][0]["xml_path"],
|
|
2782
|
+
"slide[1]/data/shape[1]",
|
|
2783
|
+
)
|
|
2784
|
+
duplicate_issue = next(
|
|
2785
|
+
issue
|
|
2786
|
+
for issue in result["slides"][0]["issues"]
|
|
2787
|
+
if issue["code"] == "duplicate_element_id"
|
|
2788
|
+
)
|
|
2789
|
+
self.assertEqual(
|
|
2790
|
+
[obj["xml_path"] for obj in duplicate_issue["related_objects"]],
|
|
2791
|
+
["slide[1]/data/shape[1]", "slide[1]/data/img[1]"],
|
|
2792
|
+
)
|
|
2793
|
+
|
|
2794
|
+
def test_normalize_issue_does_not_repeat_xml_path_hint_prefix(self) -> None:
|
|
2795
|
+
xml_path = "slide[1]/data/shape[1]"
|
|
2796
|
+
element = {
|
|
2797
|
+
"id": "box",
|
|
2798
|
+
"_source_id": "box",
|
|
2799
|
+
"_ref": xml_path,
|
|
2800
|
+
"xml_path": xml_path,
|
|
2801
|
+
"kind": "shape",
|
|
2802
|
+
"type": "rect",
|
|
2803
|
+
"x": 0,
|
|
2804
|
+
"y": 0,
|
|
2805
|
+
"width": 40,
|
|
2806
|
+
"height": 40,
|
|
2807
|
+
}
|
|
2808
|
+
prefix = "Locate via related_objects[].xml_path."
|
|
2809
|
+
|
|
2810
|
+
issue = xml_text_overlap_lint.normalize_issue(
|
|
2811
|
+
{
|
|
2812
|
+
"level": "error",
|
|
2813
|
+
"code": "shape_out_of_canvas",
|
|
2814
|
+
"elements": [xml_path],
|
|
2815
|
+
"canvas": {"width": 960, "height": 540},
|
|
2816
|
+
"bbox": {"x": -10, "y": 0, "width": 40, "height": 40},
|
|
2817
|
+
"overflow": {"left": 10, "top": 0, "right": 0, "bottom": 0},
|
|
2818
|
+
"hint": f"{prefix} Move the shape inside the canvas.",
|
|
2819
|
+
},
|
|
2820
|
+
1,
|
|
2821
|
+
{xml_path: element},
|
|
2822
|
+
)
|
|
2823
|
+
|
|
2824
|
+
self.assertEqual(issue["hint"].count(prefix), 1)
|
|
2825
|
+
|
|
2826
|
+
def test_lint_xml_elements_keep_locator_for_anonymous_related_object(self) -> None:
|
|
2827
|
+
result = xml_text_overlap_lint.lint_xml(
|
|
2828
|
+
"""
|
|
2829
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2830
|
+
<data>
|
|
2831
|
+
<shape type="text" topLeftX="100" topLeftY="100" width="300" height="100">
|
|
2832
|
+
<content fontSize="24"><p>Important text</p></content>
|
|
2833
|
+
</shape>
|
|
2834
|
+
<img id="srv-42" src="token" topLeftX="100" topLeftY="100" width="300" height="100"/>
|
|
2835
|
+
</data>
|
|
2836
|
+
</slide>
|
|
2837
|
+
"""
|
|
2838
|
+
)
|
|
2839
|
+
|
|
2840
|
+
issue = next(
|
|
2841
|
+
issue
|
|
2842
|
+
for issue in result["slides"][0]["issues"]
|
|
2843
|
+
if issue["code"] == "image_covers_text"
|
|
2844
|
+
)
|
|
2845
|
+
self.assertEqual(
|
|
2846
|
+
issue["elements"],
|
|
2847
|
+
["srv-42", "slide[1]/data/shape[1]"],
|
|
2848
|
+
)
|
|
2849
|
+
self.assertEqual(issue["element_ids"], ["srv-42"])
|
|
2850
|
+
self.assertEqual(len(issue["related_objects"]), 2)
|
|
2851
|
+
|
|
2852
|
+
def test_normalize_issue_deduplicates_repeated_element_refs(self) -> None:
|
|
2853
|
+
xml_path = "slide[1]/data/shape[1]"
|
|
2854
|
+
element = {
|
|
2855
|
+
"id": "srv-42",
|
|
2856
|
+
"_source_id": "srv-42",
|
|
2857
|
+
"_ref": xml_path,
|
|
2858
|
+
"xml_path": xml_path,
|
|
2859
|
+
"kind": "shape",
|
|
2860
|
+
"type": "rect",
|
|
2861
|
+
"x": 0,
|
|
2862
|
+
"y": 0,
|
|
2863
|
+
"width": 40,
|
|
2864
|
+
"height": 40,
|
|
2865
|
+
}
|
|
2866
|
+
|
|
2867
|
+
issue = xml_text_overlap_lint.normalize_issue(
|
|
2868
|
+
{
|
|
2869
|
+
"level": "warning",
|
|
2870
|
+
"code": "blank_slide",
|
|
2871
|
+
"measurement": {
|
|
2872
|
+
"visible_element_count": 0,
|
|
2873
|
+
"declared_element_count": 1,
|
|
2874
|
+
},
|
|
2875
|
+
"elements": [xml_path, xml_path],
|
|
2876
|
+
},
|
|
2877
|
+
1,
|
|
2878
|
+
{xml_path: element},
|
|
2879
|
+
)
|
|
2880
|
+
|
|
2881
|
+
self.assertEqual(issue["elements"], ["srv-42"])
|
|
2882
|
+
self.assertEqual(issue["element_ids"], ["srv-42"])
|
|
2883
|
+
self.assertEqual(len(issue["related_objects"]), 1)
|
|
2884
|
+
|
|
2885
|
+
def test_lint_xml_reports_duplicate_ids_for_every_linted_element_kind(self) -> None:
|
|
2886
|
+
duplicate_pairs = {
|
|
2887
|
+
"shape": (
|
|
2888
|
+
'<shape id="dup" type="rect" topLeftX="10" topLeftY="10" width="40" height="40"/>',
|
|
2889
|
+
'<shape id="dup" type="rect" topLeftX="60" topLeftY="10" width="40" height="40"/>',
|
|
2890
|
+
),
|
|
2891
|
+
"chart": (
|
|
2892
|
+
'<chart id="dup" topLeftX="10" topLeftY="10" width="40" height="40"><chartPlotArea><chartPlot type="line"/></chartPlotArea><chartData><dim1><chartField name="category" valueType="string">A</chartField></dim1><dim2><chartField name="value" valueType="number">1</chartField></dim2></chartData></chart>',
|
|
2893
|
+
'<chart id="dup" topLeftX="60" topLeftY="10" width="40" height="40"><chartPlotArea><chartPlot type="line"/></chartPlotArea><chartData><dim1><chartField name="category" valueType="string">A</chartField></dim1><dim2><chartField name="value" valueType="number">1</chartField></dim2></chartData></chart>',
|
|
2894
|
+
),
|
|
2895
|
+
"table": (
|
|
2896
|
+
'<table id="dup" topLeftX="10" topLeftY="10" width="40" height="40"><colgroup><col width="40"/></colgroup><tr height="40"><td/></tr></table>',
|
|
2897
|
+
'<table id="dup" topLeftX="60" topLeftY="10" width="40" height="40"><colgroup><col width="40"/></colgroup><tr height="40"><td/></tr></table>',
|
|
2898
|
+
),
|
|
2899
|
+
"img": (
|
|
2900
|
+
'<img id="dup" src="token" topLeftX="10" topLeftY="10" width="40" height="40"/>',
|
|
2901
|
+
'<img id="dup" src="token" topLeftX="60" topLeftY="10" width="40" height="40"/>',
|
|
2902
|
+
),
|
|
2903
|
+
"line": (
|
|
2904
|
+
'<line id="dup" startX="10" startY="10" endX="40" endY="40"><border color="rgb(0, 0, 0)"/></line>',
|
|
2905
|
+
'<line id="dup" startX="60" startY="10" endX="90" endY="40"><border color="rgb(0, 0, 0)"/></line>',
|
|
2906
|
+
),
|
|
2907
|
+
"icon": (
|
|
2908
|
+
'<icon id="dup" iconType="iconpark/Base/setting.svg" topLeftX="10" topLeftY="10" width="40" height="40"><fill><fillColor color="rgb(0, 0, 0)"/></fill></icon>',
|
|
2909
|
+
'<icon id="dup" iconType="iconpark/Base/setting.svg" topLeftX="60" topLeftY="10" width="40" height="40"><fill><fillColor color="rgb(0, 0, 0)"/></fill></icon>',
|
|
2910
|
+
),
|
|
2911
|
+
"polyline": (
|
|
2912
|
+
'<polyline id="dup" topLeftX="10" topLeftY="10" width="40" height="40"><border color="rgb(0, 0, 0)"/></polyline>',
|
|
2913
|
+
'<polyline id="dup" topLeftX="60" topLeftY="10" width="40" height="40"><border color="rgb(0, 0, 0)"/></polyline>',
|
|
2914
|
+
),
|
|
2915
|
+
}
|
|
2916
|
+
for kind, pair in duplicate_pairs.items():
|
|
2917
|
+
with self.subTest(kind=kind):
|
|
2918
|
+
result = xml_text_overlap_lint.lint_xml(
|
|
2919
|
+
f'<slide xmlns="https://www.larkoffice.com/sml/2.0"><data>{pair[0]}{pair[1]}</data></slide>'
|
|
2920
|
+
)
|
|
2921
|
+
issue = next(
|
|
2922
|
+
issue
|
|
2923
|
+
for issue in result["slides"][0]["issues"]
|
|
2924
|
+
if issue["code"] == "duplicate_element_id"
|
|
2925
|
+
)
|
|
2926
|
+
self.assertEqual(issue["element_ids"], ["dup", "dup"])
|
|
2927
|
+
self.assertEqual(
|
|
2928
|
+
[obj["xml_path"] for obj in issue["related_objects"]],
|
|
2929
|
+
[
|
|
2930
|
+
f"slide[1]/data/{kind}[1]",
|
|
2931
|
+
f"slide[1]/data/{kind}[2]",
|
|
2932
|
+
],
|
|
2933
|
+
)
|
|
2934
|
+
|
|
2935
|
+
def test_lint_xml_missing_id_does_not_collide_with_explicit_synthetic_like_id(self) -> None:
|
|
2936
|
+
result = xml_text_overlap_lint.lint_xml(
|
|
2937
|
+
"""
|
|
2938
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2939
|
+
<data>
|
|
2940
|
+
<shape type="rect" topLeftX="-20" topLeftY="40" width="50" height="50"/>
|
|
2941
|
+
<shape id="shape-1" type="rect" topLeftX="100" topLeftY="40" width="50" height="50"/>
|
|
2942
|
+
</data>
|
|
2943
|
+
</slide>
|
|
2944
|
+
"""
|
|
2945
|
+
)
|
|
2946
|
+
|
|
2947
|
+
issue = next(
|
|
2948
|
+
issue for issue in result["slides"][0]["issues"]
|
|
2949
|
+
if issue["code"] == "shape_out_of_canvas"
|
|
2950
|
+
)
|
|
2951
|
+
self.assertEqual(issue["element_ids"], [])
|
|
2952
|
+
self.assertNotIn("element_id", issue["related_objects"][0])
|
|
2953
|
+
self.assertEqual(
|
|
2954
|
+
issue["related_objects"][0]["xml_path"],
|
|
2955
|
+
"slide[1]/data/shape[1]",
|
|
2956
|
+
)
|
|
2957
|
+
self.assertTrue(
|
|
2958
|
+
issue["hint"].startswith("Locate via related_objects[].xml_path. ")
|
|
2959
|
+
)
|
|
2960
|
+
self.assertNotIn(
|
|
2961
|
+
"duplicate_element_id",
|
|
2962
|
+
[candidate["code"] for candidate in result["slides"][0]["issues"]],
|
|
2963
|
+
)
|
|
2964
|
+
|
|
2965
|
+
def test_lint_xml_empty_id_is_not_exposed_as_an_element_id(self) -> None:
|
|
2966
|
+
result = xml_text_overlap_lint.lint_xml(
|
|
2967
|
+
"""
|
|
2968
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2969
|
+
<data>
|
|
2970
|
+
<shape id="" type="rect" topLeftX="-20" topLeftY="40" width="50" height="50"/>
|
|
2971
|
+
</data>
|
|
2972
|
+
</slide>
|
|
2973
|
+
"""
|
|
2974
|
+
)
|
|
2975
|
+
|
|
2976
|
+
issue = next(
|
|
2977
|
+
issue
|
|
2978
|
+
for issue in result["slides"][0]["issues"]
|
|
2979
|
+
if issue["code"] == "shape_out_of_canvas"
|
|
2980
|
+
)
|
|
2981
|
+
self.assertEqual(issue["element_ids"], [])
|
|
2982
|
+
self.assertNotIn("element_id", issue["related_objects"][0])
|
|
2983
|
+
self.assertEqual(
|
|
2984
|
+
issue["related_objects"][0]["xml_path"],
|
|
2985
|
+
"slide[1]/data/shape[1]",
|
|
2986
|
+
)
|
|
2987
|
+
|
|
2988
|
+
def test_lint_xml_uses_resolved_table_bounds_for_canvas_validation(self) -> None:
|
|
2989
|
+
result = xml_text_overlap_lint.lint_xml(
|
|
2990
|
+
"""
|
|
2991
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
2992
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2993
|
+
<data>
|
|
2994
|
+
<table id="resolved-overflow-table" topLeftX="800" topLeftY="80" width="100" height="40">
|
|
2995
|
+
<colgroup><col width="100"/><col width="100"/></colgroup>
|
|
2996
|
+
<tr height="40"><td/><td/></tr>
|
|
2997
|
+
</table>
|
|
2998
|
+
</data>
|
|
2999
|
+
</slide>
|
|
3000
|
+
</presentation>
|
|
3001
|
+
"""
|
|
3002
|
+
)
|
|
3003
|
+
issues = result["slides"][0]["issues"]
|
|
3004
|
+
canvas_issue = next(issue for issue in issues if issue["code"] == "table_out_of_canvas")
|
|
3005
|
+
mismatch_issue = next(issue for issue in issues if issue["code"] == "table_resolved_size_mismatch")
|
|
3006
|
+
self.assertEqual(result["summary"]["error_count"], 1)
|
|
3007
|
+
self.assertEqual(canvas_issue["bbox"], {"x": 800, "y": 80, "width": 200, "height": 40})
|
|
3008
|
+
self.assertEqual(canvas_issue["overflow"]["right"], 40)
|
|
3009
|
+
self.assertEqual(mismatch_issue["dimension"], "width")
|
|
3010
|
+
self.assertEqual(mismatch_issue["resolved_size"], canvas_issue["bbox"]["width"])
|
|
3011
|
+
|
|
3012
|
+
def test_lint_xml_uses_the_same_anonymous_table_path_for_all_table_diagnostics(self) -> None:
|
|
3013
|
+
result = xml_text_overlap_lint.lint_xml(
|
|
3014
|
+
"""
|
|
3015
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
3016
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
3017
|
+
<data>
|
|
3018
|
+
<shape id="title" type="text" topLeftX="40" topLeftY="40" width="200" height="40"/>
|
|
3019
|
+
<img id="logo" src="token" topLeftX="40" topLeftY="100" width="40" height="40"/>
|
|
3020
|
+
<table topLeftX="900" topLeftY="80" width="100" height="40">
|
|
3021
|
+
<colgroup><col width="100"/><col width="100"/></colgroup>
|
|
3022
|
+
<tr height="40"><td/><td/></tr>
|
|
3023
|
+
</table>
|
|
3024
|
+
</data>
|
|
3025
|
+
</slide>
|
|
3026
|
+
</presentation>
|
|
3027
|
+
"""
|
|
3028
|
+
)
|
|
3029
|
+
issues = result["slides"][0]["issues"]
|
|
3030
|
+
canvas_issue = next(issue for issue in issues if issue["code"] == "table_out_of_canvas")
|
|
3031
|
+
mismatch_issue = next(issue for issue in issues if issue["code"] == "table_resolved_size_mismatch")
|
|
3032
|
+
self.assertEqual(canvas_issue["elements"], ["slide[1]/data/table[1]"])
|
|
3033
|
+
self.assertEqual(mismatch_issue["elements"], ["slide[1]/data/table[1]"])
|
|
3034
|
+
self.assertEqual(
|
|
3035
|
+
canvas_issue["related_objects"][0]["xml_path"],
|
|
3036
|
+
"slide[1]/data/table[1]",
|
|
3037
|
+
)
|
|
3038
|
+
self.assertEqual(
|
|
3039
|
+
mismatch_issue["related_objects"][0]["xml_path"],
|
|
3040
|
+
"slide[1]/data/table[1]",
|
|
3041
|
+
)
|
|
3042
|
+
self.assertNotIn("element_id", canvas_issue["related_objects"][0])
|
|
3043
|
+
self.assertNotIn("element_id", mismatch_issue["related_objects"][0])
|
|
3044
|
+
|
|
3045
|
+
def test_lint_xml_reports_info_when_table_target_size_resolves_larger_than_declared(self) -> None:
|
|
3046
|
+
result = xml_text_overlap_lint.lint_xml(
|
|
3047
|
+
"""
|
|
3048
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
3049
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
3050
|
+
<data>
|
|
3051
|
+
<table id="size-mismatch" topLeftX="40" topLeftY="120" width="200" height="80">
|
|
3052
|
+
<colgroup><col span="2" width="100"/><col width="50"/></colgroup>
|
|
3053
|
+
<tr height="40"><td/><td/><td/></tr>
|
|
3054
|
+
<tr height="60"><td/><td/><td/></tr>
|
|
3055
|
+
</table>
|
|
3056
|
+
</data>
|
|
3057
|
+
</slide>
|
|
3058
|
+
</presentation>
|
|
3059
|
+
"""
|
|
3060
|
+
)
|
|
3061
|
+
issues_by_dimension = {issue["dimension"]: issue for issue in result["slides"][0]["issues"]}
|
|
3062
|
+
self.assertEqual(result["summary"]["error_count"], 0)
|
|
3063
|
+
self.assertEqual(result["summary"]["warning_count"], 0)
|
|
3064
|
+
self.assertEqual(result["summary"]["info_count"], 2)
|
|
3065
|
+
self.assertEqual(issues_by_dimension["width"]["level"], "info")
|
|
3066
|
+
self.assertEqual(issues_by_dimension["width"]["code"], "table_resolved_size_mismatch")
|
|
3067
|
+
self.assertEqual(issues_by_dimension["width"]["resolved_sizes"], [100, 100, 50])
|
|
2300
3068
|
self.assertEqual(issues_by_dimension["width"]["resolved_size"], 250)
|
|
2301
3069
|
self.assertEqual(issues_by_dimension["height"]["resolved_sizes"], [40, 60])
|
|
2302
3070
|
self.assertEqual(issues_by_dimension["height"]["resolved_size"], 100)
|
|
@@ -2304,8 +3072,8 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
2304
3072
|
def test_lint_xml_does_not_report_info_when_table_target_size_is_resolved_exactly(self) -> None:
|
|
2305
3073
|
result = xml_text_overlap_lint.lint_xml(
|
|
2306
3074
|
"""
|
|
2307
|
-
<presentation xmlns="
|
|
2308
|
-
<slide xmlns="
|
|
3075
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
3076
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2309
3077
|
<data>
|
|
2310
3078
|
<table id="size-match" topLeftX="40" topLeftY="120" width="300" height="100">
|
|
2311
3079
|
<colgroup><col width="100"/><col/></colgroup>
|
|
@@ -2324,8 +3092,8 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
2324
3092
|
def test_lint_xml_keeps_resolved_table_sizes_positive_when_target_is_too_small(self) -> None:
|
|
2325
3093
|
result = xml_text_overlap_lint.lint_xml(
|
|
2326
3094
|
"""
|
|
2327
|
-
<presentation xmlns="
|
|
2328
|
-
<slide xmlns="
|
|
3095
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
3096
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2329
3097
|
<data>
|
|
2330
3098
|
<table id="narrow-table" topLeftX="40" topLeftY="120" width="1">
|
|
2331
3099
|
<colgroup><col/><col/></colgroup>
|
|
@@ -2392,8 +3160,8 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
2392
3160
|
input_path = Path(temp_dir) / f"{name}.xml"
|
|
2393
3161
|
input_path.write_text(
|
|
2394
3162
|
f"""
|
|
2395
|
-
<presentation xmlns="
|
|
2396
|
-
<slide xmlns="
|
|
3163
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
3164
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0"><data>{table_xml}</data></slide>
|
|
2397
3165
|
</presentation>
|
|
2398
3166
|
""",
|
|
2399
3167
|
encoding="utf-8",
|
|
@@ -2432,8 +3200,8 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
2432
3200
|
with self.subTest(name=name):
|
|
2433
3201
|
result = xml_text_overlap_lint.lint_xml(
|
|
2434
3202
|
f"""
|
|
2435
|
-
<presentation xmlns="
|
|
2436
|
-
<slide xmlns="
|
|
3203
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
3204
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2437
3205
|
<data>{shapes}</data>
|
|
2438
3206
|
</slide>
|
|
2439
3207
|
</presentation>
|
|
@@ -2446,7 +3214,7 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
2446
3214
|
def test_lint_xml_reports_vertical_text_image_overlap_as_warning(self) -> None:
|
|
2447
3215
|
result = xml_text_overlap_lint.lint_xml(
|
|
2448
3216
|
"""
|
|
2449
|
-
<slide xmlns="
|
|
3217
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0"><data>
|
|
2450
3218
|
<shape id="text" type="text" vert="vert" topLeftX="100" topLeftY="100" width="100" height="100">
|
|
2451
3219
|
<content><p>Vertical</p></content>
|
|
2452
3220
|
</shape>
|
|
@@ -2459,12 +3227,119 @@ class XmlTextOverlapLintGeometryTest(unittest.TestCase):
|
|
|
2459
3227
|
self.assertEqual(result["summary"]["error_count"], 0)
|
|
2460
3228
|
self.assertEqual(result["summary"]["info_count"], 1)
|
|
2461
3229
|
|
|
3230
|
+
def test_lint_xml_related_objects_include_source_xml_paths(self) -> None:
|
|
3231
|
+
result = xml_text_overlap_lint.lint_xml(
|
|
3232
|
+
"""
|
|
3233
|
+
<presentation xmlns="http://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
3234
|
+
<slide>
|
|
3235
|
+
<data>
|
|
3236
|
+
<shape type="text" topLeftX="80" topLeftY="80" width="400" height="60">
|
|
3237
|
+
<content fontSize="24"><p>Control slide</p></content>
|
|
3238
|
+
</shape>
|
|
3239
|
+
</data>
|
|
3240
|
+
</slide>
|
|
3241
|
+
<slide>
|
|
3242
|
+
<data>
|
|
3243
|
+
<shape type="text" topLeftX="70" topLeftY="55" width="820" height="70">
|
|
3244
|
+
<content fontSize="32"><p>shape-3 mapping experiment</p></content>
|
|
3245
|
+
</shape>
|
|
3246
|
+
<shape type="text" topLeftX="80" topLeftY="165" width="400" height="70">
|
|
3247
|
+
<content fontSize="18"><p>First, preserve source order.</p></content>
|
|
3248
|
+
</shape>
|
|
3249
|
+
<shape type="text" topLeftX="80" topLeftY="315" width="400" height="64">
|
|
3250
|
+
<content fontSize="26"><p>TARGET_SHAPE_THREE</p></content>
|
|
3251
|
+
</shape>
|
|
3252
|
+
<img src="token" topLeftX="80" topLeftY="305" width="400" height="110"/>
|
|
3253
|
+
</data>
|
|
3254
|
+
</slide>
|
|
3255
|
+
</presentation>
|
|
3256
|
+
"""
|
|
3257
|
+
)
|
|
3258
|
+
|
|
3259
|
+
issue = next(
|
|
3260
|
+
issue
|
|
3261
|
+
for issue in result["slides"][1]["issues"]
|
|
3262
|
+
if issue["code"] == "image_covers_text"
|
|
3263
|
+
)
|
|
3264
|
+
self.assertEqual(
|
|
3265
|
+
[(obj["kind"], obj["xml_path"]) for obj in issue["related_objects"]],
|
|
3266
|
+
[
|
|
3267
|
+
("img", "slide[2]/data/img[1]"),
|
|
3268
|
+
("shape", "slide[2]/data/shape[3]"),
|
|
3269
|
+
],
|
|
3270
|
+
)
|
|
3271
|
+
self.assertTrue(
|
|
3272
|
+
all("element_id" not in obj for obj in issue["related_objects"])
|
|
3273
|
+
)
|
|
3274
|
+
|
|
3275
|
+
def test_lint_xml_related_objects_include_line_xml_path(self) -> None:
|
|
3276
|
+
result = xml_text_overlap_lint.lint_xml(
|
|
3277
|
+
"""
|
|
3278
|
+
<slide xmlns="http://www.larkoffice.com/sml/2.0">
|
|
3279
|
+
<data>
|
|
3280
|
+
<shape id="label" type="text" topLeftX="100" topLeftY="100" width="200" height="80">
|
|
3281
|
+
<content fontSize="24"><p>Crossed text</p></content>
|
|
3282
|
+
</shape>
|
|
3283
|
+
<line id="connector" startX="80" startY="130" endX="330" endY="130">
|
|
3284
|
+
<border color="rgb(15, 23, 42)" width="2"/>
|
|
3285
|
+
</line>
|
|
3286
|
+
</data>
|
|
3287
|
+
</slide>
|
|
3288
|
+
"""
|
|
3289
|
+
)
|
|
3290
|
+
|
|
3291
|
+
issue = next(
|
|
3292
|
+
issue
|
|
3293
|
+
for issue in result["slides"][0]["issues"]
|
|
3294
|
+
if issue["code"] == "bbox_overlap" and issue["elements"][0] == "connector"
|
|
3295
|
+
)
|
|
3296
|
+
self.assertEqual(
|
|
3297
|
+
{
|
|
3298
|
+
obj["element_id"]: obj["xml_path"]
|
|
3299
|
+
for obj in issue["related_objects"]
|
|
3300
|
+
},
|
|
3301
|
+
{
|
|
3302
|
+
"connector": "slide[1]/data/line[1]",
|
|
3303
|
+
"label": "slide[1]/data/shape[1]",
|
|
3304
|
+
},
|
|
3305
|
+
)
|
|
3306
|
+
|
|
2462
3307
|
|
|
2463
3308
|
class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
3309
|
+
def test_lint_xml_sparse_container_related_objects_include_icon_xml_path(self) -> None:
|
|
3310
|
+
result = xml_text_overlap_lint.lint_xml(
|
|
3311
|
+
"""
|
|
3312
|
+
<slide xmlns="http://www.larkoffice.com/sml/2.0">
|
|
3313
|
+
<data>
|
|
3314
|
+
<shape id="card" type="rect" topLeftX="60" topLeftY="120" width="400" height="300"/>
|
|
3315
|
+
<icon id="visual" iconType="iconpark/Base/setting.svg" topLeftX="80" topLeftY="140" width="32" height="32">
|
|
3316
|
+
<fill><fillColor color="rgb(37, 99, 235)"/></fill>
|
|
3317
|
+
</icon>
|
|
3318
|
+
</data>
|
|
3319
|
+
</slide>
|
|
3320
|
+
"""
|
|
3321
|
+
)
|
|
3322
|
+
|
|
3323
|
+
issue = next(
|
|
3324
|
+
issue
|
|
3325
|
+
for issue in result["slides"][0]["issues"]
|
|
3326
|
+
if issue["code"] == "sparse_container_content"
|
|
3327
|
+
)
|
|
3328
|
+
self.assertEqual(
|
|
3329
|
+
{
|
|
3330
|
+
obj["element_id"]: obj["xml_path"]
|
|
3331
|
+
for obj in issue["related_objects"]
|
|
3332
|
+
},
|
|
3333
|
+
{
|
|
3334
|
+
"card": "slide[1]/data/shape[1]",
|
|
3335
|
+
"visual": "slide[1]/data/icon[1]",
|
|
3336
|
+
},
|
|
3337
|
+
)
|
|
3338
|
+
|
|
2464
3339
|
def test_lint_xml_blocks_blank_slide(self) -> None:
|
|
2465
3340
|
result = xml_text_overlap_lint.lint_xml(
|
|
2466
3341
|
"""
|
|
2467
|
-
<presentation xmlns="
|
|
3342
|
+
<presentation xmlns="https://www.larkoffice.com/sml/2.0" width="960" height="540">
|
|
2468
3343
|
<slide id="content-slide">
|
|
2469
3344
|
<data>
|
|
2470
3345
|
<shape id="title" type="text" topLeftX="60" topLeftY="60" width="400" height="50">
|
|
@@ -2499,7 +3374,7 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
2499
3374
|
def test_lint_xml_blocks_blank_slide_with_only_transparent_image(self) -> None:
|
|
2500
3375
|
result = xml_text_overlap_lint.lint_xml(
|
|
2501
3376
|
"""
|
|
2502
|
-
<slide xmlns="
|
|
3377
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2503
3378
|
<data>
|
|
2504
3379
|
<img id="ghost" src="token" topLeftX="60" topLeftY="60" width="200" height="200" alpha="0"/>
|
|
2505
3380
|
</data>
|
|
@@ -2514,7 +3389,7 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
2514
3389
|
def test_lint_xml_warns_when_large_container_is_mostly_empty(self) -> None:
|
|
2515
3390
|
result = xml_text_overlap_lint.lint_xml(
|
|
2516
3391
|
"""
|
|
2517
|
-
<slide xmlns="
|
|
3392
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2518
3393
|
<data>
|
|
2519
3394
|
<shape id="trend-card" type="rect" topLeftX="500" topLeftY="135" width="410" height="370"/>
|
|
2520
3395
|
<shape id="trend-title" type="text" topLeftX="515" topLeftY="147" width="380" height="28">
|
|
@@ -2534,6 +3409,7 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
2534
3409
|
self.assertEqual(issue["target"], {
|
|
2535
3410
|
"slide_number": 1,
|
|
2536
3411
|
"container_id": "trend-card",
|
|
3412
|
+
"container_xml_path": "slide[1]/data/shape[1]",
|
|
2537
3413
|
"container_type": "rect",
|
|
2538
3414
|
"bbox": {"x": 500, "y": 135, "width": 410, "height": 370},
|
|
2539
3415
|
})
|
|
@@ -2555,10 +3431,39 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
2555
3431
|
self.assertEqual(result["slides"][0]["status"], "needs_screenshot_review")
|
|
2556
3432
|
self.assertEqual(result["slides"][0]["warnings"], result["slides"][0]["issues"])
|
|
2557
3433
|
|
|
3434
|
+
def test_lint_xml_uses_xml_path_in_anonymous_sparse_container_message(self) -> None:
|
|
3435
|
+
result = xml_text_overlap_lint.lint_xml(
|
|
3436
|
+
"""
|
|
3437
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
3438
|
+
<data>
|
|
3439
|
+
<shape type="rect" topLeftX="500" topLeftY="135" width="410" height="370"/>
|
|
3440
|
+
<shape id="trend-title" type="text" topLeftX="515" topLeftY="147" width="380" height="28">
|
|
3441
|
+
<content fontSize="15"><p>Core trends</p></content>
|
|
3442
|
+
</shape>
|
|
3443
|
+
</data>
|
|
3444
|
+
</slide>
|
|
3445
|
+
"""
|
|
3446
|
+
)
|
|
3447
|
+
|
|
3448
|
+
issue = next(
|
|
3449
|
+
issue
|
|
3450
|
+
for issue in result["slides"][0]["issues"]
|
|
3451
|
+
if issue["code"] == "sparse_container_content"
|
|
3452
|
+
)
|
|
3453
|
+
self.assertNotIn("container_id", issue["target"])
|
|
3454
|
+
self.assertEqual(
|
|
3455
|
+
issue["target"]["container_xml_path"],
|
|
3456
|
+
"slide[1]/data/shape[1]",
|
|
3457
|
+
)
|
|
3458
|
+
self.assertEqual(
|
|
3459
|
+
issue["message"],
|
|
3460
|
+
"large card slide[1]/data/shape[1] content coverage 1.0% is below 15.0%",
|
|
3461
|
+
)
|
|
3462
|
+
|
|
2558
3463
|
def test_lint_xml_warns_for_sparse_short_cards(self) -> None:
|
|
2559
3464
|
result = xml_text_overlap_lint.lint_xml(
|
|
2560
3465
|
"""
|
|
2561
|
-
<slide xmlns="
|
|
3466
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2562
3467
|
<data>
|
|
2563
3468
|
<shape id="card-1" type="rect" topLeftX="60" topLeftY="180" width="400" height="105"/>
|
|
2564
3469
|
<shape id="text-1" type="text" topLeftX="80" topLeftY="220" width="360" height="30">
|
|
@@ -2604,7 +3509,7 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
2604
3509
|
def test_lint_xml_warns_when_whole_slide_has_too_little_effective_content(self) -> None:
|
|
2605
3510
|
result = xml_text_overlap_lint.lint_xml(
|
|
2606
3511
|
"""
|
|
2607
|
-
<slide xmlns="
|
|
3512
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2608
3513
|
<data>
|
|
2609
3514
|
<shape id="background" type="rect" topLeftX="0" topLeftY="0" width="960" height="540"/>
|
|
2610
3515
|
<shape id="text-1" type="text" topLeftX="60" topLeftY="80" width="200" height="30">
|
|
@@ -2636,7 +3541,7 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
2636
3541
|
def test_lint_xml_ignores_isolated_short_layout_bar(self) -> None:
|
|
2637
3542
|
result = xml_text_overlap_lint.lint_xml(
|
|
2638
3543
|
"""
|
|
2639
|
-
<slide xmlns="
|
|
3544
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2640
3545
|
<data>
|
|
2641
3546
|
<shape id="summary-bar" type="rect" topLeftX="52" topLeftY="82" width="856" height="105"/>
|
|
2642
3547
|
<shape id="summary" type="text" topLeftX="72" topLeftY="115" width="816" height="30">
|
|
@@ -2652,7 +3557,7 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
2652
3557
|
def test_lint_xml_counts_rect_own_content_as_visible_content(self) -> None:
|
|
2653
3558
|
result = xml_text_overlap_lint.lint_xml(
|
|
2654
3559
|
"""
|
|
2655
|
-
<slide xmlns="
|
|
3560
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2656
3561
|
<data>
|
|
2657
3562
|
<shape id="load-card" type="rect" topLeftX="60" topLeftY="140" width="220" height="184">
|
|
2658
3563
|
<content fontSize="18">
|
|
@@ -2671,7 +3576,7 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
2671
3576
|
def test_lint_xml_reports_nonzero_coverage_for_rect_own_content_reproduction(self) -> None:
|
|
2672
3577
|
result = xml_text_overlap_lint.lint_xml(
|
|
2673
3578
|
"""
|
|
2674
|
-
<slide xmlns="
|
|
3579
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2675
3580
|
<data>
|
|
2676
3581
|
<shape id="load-card" type="rect" topLeftX="60" topLeftY="140" width="220" height="184">
|
|
2677
3582
|
<content fontSize="18">
|
|
@@ -2693,7 +3598,7 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
2693
3598
|
def test_lint_xml_still_warns_for_sparse_rect_own_content(self) -> None:
|
|
2694
3599
|
result = xml_text_overlap_lint.lint_xml(
|
|
2695
3600
|
"""
|
|
2696
|
-
<slide xmlns="
|
|
3601
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2697
3602
|
<data>
|
|
2698
3603
|
<shape id="sparse-card" type="rect" topLeftX="60" topLeftY="140" width="220" height="184">
|
|
2699
3604
|
<content fontSize="12"><p>A</p></content>
|
|
@@ -2712,7 +3617,7 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
2712
3617
|
def test_lint_xml_unions_rect_own_content_with_child_content(self) -> None:
|
|
2713
3618
|
self_only = xml_text_overlap_lint.lint_xml(
|
|
2714
3619
|
"""
|
|
2715
|
-
<slide xmlns="
|
|
3620
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2716
3621
|
<data>
|
|
2717
3622
|
<shape id="card" type="rect" topLeftX="60" topLeftY="140" width="220" height="184">
|
|
2718
3623
|
<content fontSize="12"><p>A</p></content>
|
|
@@ -2723,7 +3628,7 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
2723
3628
|
)
|
|
2724
3629
|
with_overlapping_child = xml_text_overlap_lint.lint_xml(
|
|
2725
3630
|
"""
|
|
2726
|
-
<slide xmlns="
|
|
3631
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2727
3632
|
<data>
|
|
2728
3633
|
<shape id="card" type="rect" topLeftX="60" topLeftY="140" width="220" height="184">
|
|
2729
3634
|
<content fontSize="12"><p>A</p></content>
|
|
@@ -2747,7 +3652,7 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
2747
3652
|
def test_extract_density_elements_reads_nested_font_size_from_rect_content(self) -> None:
|
|
2748
3653
|
elements = xml_text_overlap_lint.extract_density_elements(
|
|
2749
3654
|
"""
|
|
2750
|
-
<slide xmlns="
|
|
3655
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2751
3656
|
<data>
|
|
2752
3657
|
<shape id="card" type="rect" topLeftX="60" topLeftY="140" width="220" height="184">
|
|
2753
3658
|
<content fontSize="12"><p><span fontSize="36">32.0 t</span></p></content>
|
|
@@ -2762,7 +3667,7 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
2762
3667
|
def test_extract_density_elements_does_not_attach_following_text_to_self_closing_rect(self) -> None:
|
|
2763
3668
|
elements = xml_text_overlap_lint.extract_density_elements(
|
|
2764
3669
|
"""
|
|
2765
|
-
<slide xmlns="
|
|
3670
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2766
3671
|
<data>
|
|
2767
3672
|
<shape id="card" type="rect" topLeftX="60" topLeftY="140" width="220" height="184"/>
|
|
2768
3673
|
<shape id="title" type="text" topLeftX="80" topLeftY="160" width="180" height="30">
|
|
@@ -2779,7 +3684,7 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
2779
3684
|
def test_lint_xml_allows_container_with_large_visual_child(self) -> None:
|
|
2780
3685
|
result = xml_text_overlap_lint.lint_xml(
|
|
2781
3686
|
"""
|
|
2782
|
-
<slide xmlns="
|
|
3687
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2783
3688
|
<data>
|
|
2784
3689
|
<shape id="chart-card" type="rect" topLeftX="500" topLeftY="135" width="410" height="300"/>
|
|
2785
3690
|
<chart id="chart" topLeftX="525" topLeftY="170" width="350" height="220">
|
|
@@ -2799,7 +3704,7 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
2799
3704
|
def test_lint_xml_does_not_let_transparent_visual_child_suppress_sparse_warning(self) -> None:
|
|
2800
3705
|
result = xml_text_overlap_lint.lint_xml(
|
|
2801
3706
|
"""
|
|
2802
|
-
<slide xmlns="
|
|
3707
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2803
3708
|
<data>
|
|
2804
3709
|
<shape id="title" type="text" topLeftX="40" topLeftY="40" width="300" height="40">
|
|
2805
3710
|
<content fontSize="20"><p>Section title</p></content>
|
|
@@ -2825,7 +3730,7 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
2825
3730
|
def test_lint_xml_warns_for_small_empty_visual_placeholder_cards(self) -> None:
|
|
2826
3731
|
result = xml_text_overlap_lint.lint_xml(
|
|
2827
3732
|
"""
|
|
2828
|
-
<slide xmlns="
|
|
3733
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2829
3734
|
<data>
|
|
2830
3735
|
<shape id="letter-placeholder" type="rect" topLeftX="520" topLeftY="180" width="200" height="200"/>
|
|
2831
3736
|
<shape id="letter" type="text" topLeftX="540" topLeftY="250" width="160" height="70">
|
|
@@ -2847,7 +3752,7 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
2847
3752
|
def test_lint_xml_applies_global_threshold_to_normal_text_card(self) -> None:
|
|
2848
3753
|
result = xml_text_overlap_lint.lint_xml(
|
|
2849
3754
|
"""
|
|
2850
|
-
<slide xmlns="
|
|
3755
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2851
3756
|
<data>
|
|
2852
3757
|
<shape id="card" type="rect" topLeftX="70" topLeftY="184" width="260" height="288"/>
|
|
2853
3758
|
<shape id="title" type="text" topLeftX="90" topLeftY="215" width="220" height="30">
|
|
@@ -2868,7 +3773,7 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
2868
3773
|
def test_lint_xml_allows_image_overlay_rect(self) -> None:
|
|
2869
3774
|
result = xml_text_overlap_lint.lint_xml(
|
|
2870
3775
|
"""
|
|
2871
|
-
<slide xmlns="
|
|
3776
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2872
3777
|
<data>
|
|
2873
3778
|
<img id="hero" topLeftX="560" topLeftY="0" width="400" height="540"/>
|
|
2874
3779
|
<shape id="tint" type="rect" topLeftX="560" topLeftY="0" width="400" height="540"/>
|
|
@@ -2882,7 +3787,7 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
2882
3787
|
def test_lint_xml_does_not_let_transparent_image_overlay_suppress_sparse_warning(self) -> None:
|
|
2883
3788
|
result = xml_text_overlap_lint.lint_xml(
|
|
2884
3789
|
"""
|
|
2885
|
-
<slide xmlns="
|
|
3790
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2886
3791
|
<data>
|
|
2887
3792
|
<shape id="title" type="text" topLeftX="40" topLeftY="40" width="300" height="40">
|
|
2888
3793
|
<content fontSize="20"><p>Section title</p></content>
|
|
@@ -2902,7 +3807,7 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
2902
3807
|
def test_lint_xml_allows_edge_spanning_layout_panel_and_nested_decoration(self) -> None:
|
|
2903
3808
|
result = xml_text_overlap_lint.lint_xml(
|
|
2904
3809
|
"""
|
|
2905
|
-
<slide xmlns="
|
|
3810
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2906
3811
|
<data>
|
|
2907
3812
|
<shape id="panel" type="rect" topLeftX="600" topLeftY="0" width="360" height="540"/>
|
|
2908
3813
|
<shape id="decoration" type="rect" topLeftX="660" topLeftY="150" width="240" height="240"/>
|
|
@@ -2916,7 +3821,7 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
2916
3821
|
def test_lint_xml_counts_icons_as_visible_content(self) -> None:
|
|
2917
3822
|
result = xml_text_overlap_lint.lint_xml(
|
|
2918
3823
|
"""
|
|
2919
|
-
<slide xmlns="
|
|
3824
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2920
3825
|
<data>
|
|
2921
3826
|
<shape id="card" type="rect" topLeftX="80" topLeftY="140" width="320" height="240"/>
|
|
2922
3827
|
<icon id="visual" iconType="iconpark/Safe/shield.svg" topLeftX="100" topLeftY="160" width="180" height="180">
|
|
@@ -2932,7 +3837,7 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
2932
3837
|
def test_lint_xml_does_not_count_transparent_icon_as_visible_content(self) -> None:
|
|
2933
3838
|
result = xml_text_overlap_lint.lint_xml(
|
|
2934
3839
|
"""
|
|
2935
|
-
<slide xmlns="
|
|
3840
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2936
3841
|
<data>
|
|
2937
3842
|
<shape id="title" type="text" topLeftX="40" topLeftY="40" width="300" height="40">
|
|
2938
3843
|
<content fontSize="20"><p>Section title</p></content>
|
|
@@ -2955,7 +3860,7 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
2955
3860
|
def test_lint_xml_warns_when_coverage_is_below_global_threshold(self) -> None:
|
|
2956
3861
|
result = xml_text_overlap_lint.lint_xml(
|
|
2957
3862
|
"""
|
|
2958
|
-
<slide xmlns="
|
|
3863
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2959
3864
|
<data>
|
|
2960
3865
|
<shape id="card" type="rect" topLeftX="80" topLeftY="140" width="200" height="200"/>
|
|
2961
3866
|
<icon id="visual" iconType="iconpark/Safe/shield.svg" topLeftX="100" topLeftY="160" width="70" height="70">
|
|
@@ -2974,7 +3879,7 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
2974
3879
|
def test_lint_xml_allows_quarter_coverage_under_lower_threshold(self) -> None:
|
|
2975
3880
|
result = xml_text_overlap_lint.lint_xml(
|
|
2976
3881
|
"""
|
|
2977
|
-
<slide xmlns="
|
|
3882
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2978
3883
|
<data>
|
|
2979
3884
|
<shape id="card" type="rect" topLeftX="80" topLeftY="140" width="200" height="200"/>
|
|
2980
3885
|
<icon id="visual" iconType="iconpark/Safe/shield.svg" topLeftX="100" topLeftY="160" width="100" height="100">
|
|
@@ -2990,7 +3895,7 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
2990
3895
|
def test_lint_xml_allows_large_metric_card_above_lower_threshold(self) -> None:
|
|
2991
3896
|
result = xml_text_overlap_lint.lint_xml(
|
|
2992
3897
|
"""
|
|
2993
|
-
<slide xmlns="
|
|
3898
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
2994
3899
|
<data>
|
|
2995
3900
|
<shape id="metric-card" type="rect" topLeftX="80" topLeftY="140" width="360" height="300"/>
|
|
2996
3901
|
<shape id="metric" type="text" topLeftX="104" topLeftY="190" width="340" height="90">
|
|
@@ -3003,10 +3908,29 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
3003
3908
|
|
|
3004
3909
|
self.assertEqual(result["slides"][0]["issues"], [])
|
|
3005
3910
|
|
|
3006
|
-
def
|
|
3911
|
+
def test_lint_xml_does_not_report_blank_slide_for_embed_only_content(self) -> None:
|
|
3007
3912
|
result = xml_text_overlap_lint.lint_xml(
|
|
3008
3913
|
"""
|
|
3009
3914
|
<slide xmlns="http://www.larkoffice.com/sml/2.0">
|
|
3915
|
+
<data>
|
|
3916
|
+
<embed id="emb" topLeftX="280" topLeftY="130" width="400" height="280">
|
|
3917
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 280">
|
|
3918
|
+
<circle cx="200" cy="140" r="100" fill="#2563EB"/>
|
|
3919
|
+
</svg>
|
|
3920
|
+
</embed>
|
|
3921
|
+
</data>
|
|
3922
|
+
</slide>
|
|
3923
|
+
"""
|
|
3924
|
+
)
|
|
3925
|
+
|
|
3926
|
+
self.assertEqual(result["summary"]["error_count"], 0)
|
|
3927
|
+
codes = [issue["code"] for issue in result["slides"][0]["issues"]]
|
|
3928
|
+
self.assertNotIn("blank_slide", codes)
|
|
3929
|
+
|
|
3930
|
+
def test_lint_xml_does_not_report_blank_slide_for_line_only_content(self) -> None:
|
|
3931
|
+
result = xml_text_overlap_lint.lint_xml(
|
|
3932
|
+
"""
|
|
3933
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
3010
3934
|
<data>
|
|
3011
3935
|
<line id="l1" startX="100" startY="100" endX="800" endY="100"><border/></line>
|
|
3012
3936
|
<line id="l2" startX="100" startY="200" endX="800" endY="200"><border/></line>
|
|
@@ -3024,7 +3948,7 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
3024
3948
|
def test_lint_xml_reports_bbox_overlap_measurement_from_decision_time_visual_bbox(self) -> None:
|
|
3025
3949
|
result = xml_text_overlap_lint.lint_xml(
|
|
3026
3950
|
"""
|
|
3027
|
-
<slide xmlns="
|
|
3951
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
3028
3952
|
<data>
|
|
3029
3953
|
<shape id="left" type="text" topLeftX="80" topLeftY="80" width="300" height="60">
|
|
3030
3954
|
<content fontSize="14"><p>overlap text <span fontSize="96">big</span></p></content>
|
|
@@ -3061,7 +3985,7 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
3061
3985
|
def test_lint_xml_reports_schema_version_2_for_sparse_issues(self) -> None:
|
|
3062
3986
|
result = xml_text_overlap_lint.lint_xml(
|
|
3063
3987
|
"""
|
|
3064
|
-
<slide xmlns="
|
|
3988
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
3065
3989
|
<data>
|
|
3066
3990
|
<shape id="card" type="rect" topLeftX="60" topLeftY="140" width="220" height="184"/>
|
|
3067
3991
|
</data>
|
|
@@ -3077,7 +4001,7 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
3077
4001
|
def test_lint_xml_does_not_report_blank_slide_for_textless_decorative_shapes(self) -> None:
|
|
3078
4002
|
result = xml_text_overlap_lint.lint_xml(
|
|
3079
4003
|
"""
|
|
3080
|
-
<slide xmlns="
|
|
4004
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
3081
4005
|
<data>
|
|
3082
4006
|
<shape id="deco1" type="ellipse" topLeftX="60" topLeftY="60" width="300" height="300">
|
|
3083
4007
|
<fill><fillColor color="rgba(37, 99, 235, 1)"/></fill>
|
|
@@ -3101,7 +4025,7 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
3101
4025
|
# trivially "pass" that density check.
|
|
3102
4026
|
result = xml_text_overlap_lint.lint_xml(
|
|
3103
4027
|
"""
|
|
3104
|
-
<slide xmlns="
|
|
4028
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
3105
4029
|
<data>
|
|
3106
4030
|
<shape id="background" type="rect" topLeftX="0" topLeftY="0" width="960" height="540"/>
|
|
3107
4031
|
<shape id="text-1" type="text" topLeftX="60" topLeftY="80" width="200" height="30">
|
|
@@ -3127,7 +4051,7 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
3127
4051
|
def test_lint_xml_accepts_whitespace_around_attribute_equals_sign(self) -> None:
|
|
3128
4052
|
result = xml_text_overlap_lint.lint_xml(
|
|
3129
4053
|
"""
|
|
3130
|
-
<slide xmlns="
|
|
4054
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
3131
4055
|
<data>
|
|
3132
4056
|
<shape id="visible" type="text" topLeftX = "80" topLeftY = "80" width = "300" height = "60">
|
|
3133
4057
|
<content><p>hello</p></content>
|
|
@@ -3144,7 +4068,7 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
3144
4068
|
def test_lint_xml_reports_blank_slide_for_full_canvas_background_only(self) -> None:
|
|
3145
4069
|
result = xml_text_overlap_lint.lint_xml(
|
|
3146
4070
|
"""
|
|
3147
|
-
<slide xmlns="
|
|
4071
|
+
<slide xmlns="https://www.larkoffice.com/sml/2.0">
|
|
3148
4072
|
<data>
|
|
3149
4073
|
<shape id="background" type="rect" topLeftX="0" topLeftY="0" width="960" height="540">
|
|
3150
4074
|
<fill><fillColor color="rgba(240, 235, 220, 1)"/></fill>
|
|
@@ -3173,7 +4097,7 @@ class XmlTextOverlapLintDensityTest(unittest.TestCase):
|
|
|
3173
4097
|
)
|
|
3174
4098
|
|
|
3175
4099
|
|
|
3176
|
-
SML_NAMESPACE = "
|
|
4100
|
+
SML_NAMESPACE = "https://www.larkoffice.com/sml/2.0"
|
|
3177
4101
|
|
|
3178
4102
|
|
|
3179
4103
|
class SxsdSyntaxTestCase(unittest.TestCase):
|