@heylemon/lemonade 0.0.3 → 0.0.5

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.
Files changed (108) hide show
  1. package/dist/build-info.json +3 -3
  2. package/dist/canvas-host/a2ui/.bundle.hash +1 -1
  3. package/dist/slack/monitor/allow-list.js +2 -0
  4. package/dist/slack/monitor/context.js +2 -1
  5. package/dist/slack/monitor/message-handler/prepare.js +6 -3
  6. package/package.json +1 -1
  7. package/skills/docx/SKILL.md +25 -30
  8. package/skills/docx/scripts/accept_changes.py +0 -17
  9. package/skills/docx/scripts/comment.py +10 -39
  10. package/skills/docx/scripts/office/helpers/merge_runs.py +1 -33
  11. package/skills/docx/scripts/office/helpers/simplify_redlines.py +0 -43
  12. package/skills/docx/scripts/office/pack.py +0 -30
  13. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -1499
  14. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -1085
  15. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -3081
  16. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -287
  17. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -1676
  18. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -174
  19. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -582
  20. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -4439
  21. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -570
  22. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -116
  23. package/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -42
  24. package/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -50
  25. package/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -49
  26. package/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -33
  27. package/skills/docx/scripts/office/soffice.py +0 -55
  28. package/skills/docx/scripts/office/unpack.py +5 -27
  29. package/skills/docx/scripts/office/validate.py +19 -14
  30. package/skills/docx/scripts/office/validators/base.py +48 -224
  31. package/skills/docx/scripts/office/validators/docx.py +44 -117
  32. package/skills/docx/scripts/office/validators/pptx.py +2 -42
  33. package/skills/docx/scripts/office/validators/redlining.py +3 -40
  34. package/skills/pdf/SKILL.md +22 -15
  35. package/skills/pdf/{FORMS.md → forms.md} +0 -14
  36. package/skills/pdf/scripts/check_bounding_boxes.py +0 -5
  37. package/skills/pdf/scripts/check_fillable_fields.py +0 -1
  38. package/skills/pdf/scripts/convert_pdf_to_images.py +0 -2
  39. package/skills/pdf/scripts/create_validation_image.py +0 -4
  40. package/skills/pdf/scripts/extract_form_field_info.py +1 -31
  41. package/skills/pdf/scripts/extract_form_structure.py +0 -9
  42. package/skills/pdf/scripts/fill_fillable_fields.py +0 -23
  43. package/skills/pdf/scripts/fill_pdf_form_with_annotations.py +3 -38
  44. package/skills/pptx/SKILL.md +2 -29
  45. package/skills/pptx/editing.md +2 -2
  46. package/skills/pptx/pptxgenjs.md +53 -8
  47. package/skills/pptx/scripts/add_slide.py +0 -30
  48. package/skills/pptx/scripts/clean.py +0 -23
  49. package/skills/pptx/scripts/office/helpers/merge_runs.py +1 -33
  50. package/skills/pptx/scripts/office/helpers/simplify_redlines.py +0 -43
  51. package/skills/pptx/scripts/office/pack.py +0 -30
  52. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -1499
  53. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -1085
  54. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -3081
  55. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -287
  56. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -1676
  57. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -174
  58. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -582
  59. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -4439
  60. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -570
  61. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -116
  62. package/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -42
  63. package/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -50
  64. package/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -49
  65. package/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -33
  66. package/skills/pptx/scripts/office/soffice.py +0 -55
  67. package/skills/pptx/scripts/office/unpack.py +5 -27
  68. package/skills/pptx/scripts/office/validate.py +19 -14
  69. package/skills/pptx/scripts/office/validators/base.py +48 -224
  70. package/skills/pptx/scripts/office/validators/docx.py +44 -117
  71. package/skills/pptx/scripts/office/validators/pptx.py +2 -42
  72. package/skills/pptx/scripts/office/validators/redlining.py +3 -40
  73. package/skills/pptx/scripts/thumbnail.py +0 -31
  74. package/skills/xlsx/SKILL.md +3 -26
  75. package/skills/xlsx/scripts/office/helpers/merge_runs.py +1 -33
  76. package/skills/xlsx/scripts/office/helpers/simplify_redlines.py +0 -43
  77. package/skills/xlsx/scripts/office/pack.py +0 -30
  78. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -1499
  79. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -1085
  80. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -3081
  81. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -287
  82. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -1676
  83. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -174
  84. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -582
  85. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -4439
  86. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -570
  87. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -116
  88. package/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -42
  89. package/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -50
  90. package/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -49
  91. package/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -33
  92. package/skills/xlsx/scripts/office/soffice.py +0 -55
  93. package/skills/xlsx/scripts/office/unpack.py +5 -27
  94. package/skills/xlsx/scripts/office/validate.py +19 -14
  95. package/skills/xlsx/scripts/office/validators/base.py +48 -224
  96. package/skills/xlsx/scripts/office/validators/docx.py +44 -117
  97. package/skills/xlsx/scripts/office/validators/pptx.py +2 -42
  98. package/skills/xlsx/scripts/office/validators/redlining.py +3 -40
  99. package/skills/xlsx/scripts/recalc.py +2 -26
  100. package/skills/docx/scripts/__init__.py +0 -1
  101. package/skills/docx/scripts/office/helpers/__init__.py +0 -0
  102. package/skills/docx/scripts/office/validators/__init__.py +0 -15
  103. package/skills/pptx/scripts/__init__.py +0 -0
  104. package/skills/pptx/scripts/office/helpers/__init__.py +0 -0
  105. package/skills/pptx/scripts/office/validators/__init__.py +0 -15
  106. package/skills/xlsx/scripts/office/helpers/__init__.py +0 -0
  107. package/skills/xlsx/scripts/office/validators/__init__.py +0 -15
  108. /package/skills/pdf/{REFERENCE.md → reference.md} +0 -0
@@ -20,14 +20,6 @@ WORD_NS = "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
20
20
 
21
21
 
22
22
  def simplify_redlines(input_dir: str) -> tuple[int, str]:
23
- """Merge adjacent tracked changes from the same author in document.xml.
24
-
25
- Args:
26
- input_dir: Path to unpacked DOCX directory
27
-
28
- Returns:
29
- (merge_count, message)
30
- """
31
23
  doc_xml = Path(input_dir) / "word" / "document.xml"
32
24
 
33
25
  if not doc_xml.exists():
@@ -39,7 +31,6 @@ def simplify_redlines(input_dir: str) -> tuple[int, str]:
39
31
 
40
32
  merge_count = 0
41
33
 
42
- # Find all paragraphs and table cells (containers for content)
43
34
  containers = _find_elements(root, "p") + _find_elements(root, "tc")
44
35
 
45
36
  for container in containers:
@@ -54,10 +45,8 @@ def simplify_redlines(input_dir: str) -> tuple[int, str]:
54
45
 
55
46
 
56
47
  def _merge_tracked_changes_in(container, tag: str) -> int:
57
- """Merge adjacent w:ins or w:del elements from the same author."""
58
48
  merge_count = 0
59
49
 
60
- # Get direct children that are tracked changes of this type
61
50
  tracked = [
62
51
  child
63
52
  for child in container.childNodes
@@ -67,7 +56,6 @@ def _merge_tracked_changes_in(container, tag: str) -> int:
67
56
  if len(tracked) < 2:
68
57
  return 0
69
58
 
70
- # Process from front: merge next into current when possible
71
59
  i = 0
72
60
  while i < len(tracked) - 1:
73
61
  curr = tracked[i]
@@ -78,7 +66,6 @@ def _merge_tracked_changes_in(container, tag: str) -> int:
78
66
  container.removeChild(next_elem)
79
67
  tracked.pop(i + 1)
80
68
  merge_count += 1
81
- # Don't increment i - try to merge more into curr
82
69
  else:
83
70
  i += 1
84
71
 
@@ -86,13 +73,11 @@ def _merge_tracked_changes_in(container, tag: str) -> int:
86
73
 
87
74
 
88
75
  def _is_element(node, tag: str) -> bool:
89
- """Check if node matches the given tag name."""
90
76
  name = node.localName or node.tagName
91
77
  return name == tag or name.endswith(f":{tag}")
92
78
 
93
79
 
94
80
  def _get_author(elem) -> str:
95
- """Get the author attribute from a tracked change element."""
96
81
  author = elem.getAttribute("w:author")
97
82
  if not author:
98
83
  for attr in elem.attributes.values():
@@ -102,12 +87,9 @@ def _get_author(elem) -> str:
102
87
 
103
88
 
104
89
  def _can_merge_tracked(elem1, elem2) -> bool:
105
- """Check if two tracked change elements can be merged."""
106
- # Must be same author
107
90
  if _get_author(elem1) != _get_author(elem2):
108
91
  return False
109
92
 
110
- # Must be truly adjacent (only whitespace between them)
111
93
  node = elem1.nextSibling
112
94
  while node and node != elem2:
113
95
  if node.nodeType == node.ELEMENT_NODE:
@@ -120,7 +102,6 @@ def _can_merge_tracked(elem1, elem2) -> bool:
120
102
 
121
103
 
122
104
  def _merge_tracked_content(target, source):
123
- """Move all children from source tracked change to target."""
124
105
  while source.firstChild:
125
106
  child = source.firstChild
126
107
  source.removeChild(child)
@@ -128,7 +109,6 @@ def _merge_tracked_content(target, source):
128
109
 
129
110
 
130
111
  def _find_elements(root, tag: str) -> list:
131
- """Find all elements matching tag name (with or without namespace)."""
132
112
  results = []
133
113
 
134
114
  def traverse(node):
@@ -144,11 +124,6 @@ def _find_elements(root, tag: str) -> list:
144
124
 
145
125
 
146
126
  def get_tracked_change_authors(doc_xml_path: Path) -> dict[str, int]:
147
- """Get authors and their tracked change counts from a document.xml file.
148
-
149
- Returns:
150
- Dict mapping author name to count of tracked changes (w:ins + w:del)
151
- """
152
127
  if not doc_xml_path.exists():
153
128
  return {}
154
129
 
@@ -172,7 +147,6 @@ def get_tracked_change_authors(doc_xml_path: Path) -> dict[str, int]:
172
147
 
173
148
 
174
149
  def _get_authors_from_docx(docx_path: Path) -> dict[str, int]:
175
- """Get authors and counts from a packed DOCX file."""
176
150
  try:
177
151
  with zipfile.ZipFile(docx_path, "r") as zf:
178
152
  if "word/document.xml" not in zf.namelist():
@@ -196,22 +170,6 @@ def _get_authors_from_docx(docx_path: Path) -> dict[str, int]:
196
170
 
197
171
 
198
172
  def infer_author(modified_dir: Path, original_docx: Path, default: str = "Claude") -> str:
199
- """Infer the author to validate by finding who added tracked changes.
200
-
201
- Compares tracked change counts between modified and original documents.
202
- Returns the author who added new tracked changes.
203
-
204
- Args:
205
- modified_dir: Path to unpacked DOCX directory
206
- original_docx: Path to original DOCX file
207
- default: Default author if no new changes found
208
-
209
- Returns:
210
- Author name to use for validation
211
-
212
- Raises:
213
- ValueError: If multiple authors added new changes (ambiguous)
214
- """
215
173
  modified_xml = modified_dir / "word" / "document.xml"
216
174
  modified_authors = get_tracked_change_authors(modified_xml)
217
175
 
@@ -220,7 +178,6 @@ def infer_author(modified_dir: Path, original_docx: Path, default: str = "Claude
220
178
 
221
179
  original_authors = _get_authors_from_docx(original_docx)
222
180
 
223
- # Calculate new changes per author (modified count - original count)
224
181
  new_changes: dict[str, int] = {}
225
182
  for author, count in modified_authors.items():
226
183
  original_count = original_authors.get(author, 0)
@@ -1,4 +1,3 @@
1
- #!/usr/bin/env python3
2
1
  """Pack a directory into a DOCX, PPTX, or XLSX file.
3
2
 
4
3
  Validates with auto-repair, condenses XML formatting, and creates the Office file.
@@ -29,18 +28,6 @@ def pack(
29
28
  validate: bool = True,
30
29
  infer_author_func=None,
31
30
  ) -> tuple[None, str]:
32
- """Pack a directory into an Office file (DOCX, PPTX, or XLSX).
33
-
34
- Args:
35
- input_directory: Path to unpacked Office document directory
36
- output_file: Path to output Office file
37
- original_file: Path to original file for validation comparison
38
- validate: If True, run validation with auto-repair before packing
39
- infer_author_func: Optional function to infer author for redlining validation
40
-
41
- Returns:
42
- (None, message) - message indicates success or failure
43
- """
44
31
  input_dir = Path(input_directory)
45
32
  output_path = Path(output_file)
46
33
  suffix = output_path.suffix.lower()
@@ -51,7 +38,6 @@ def pack(
51
38
  if suffix not in {".docx", ".pptx", ".xlsx"}:
52
39
  return None, f"Error: {output_file} must be a .docx, .pptx, or .xlsx file"
53
40
 
54
- # Validate with auto-repair if requested and original file provided
55
41
  if validate and original_file:
56
42
  original_path = Path(original_file)
57
43
  if original_path.exists():
@@ -63,17 +49,14 @@ def pack(
63
49
  if not success:
64
50
  return None, f"Error: Validation failed for {input_dir}"
65
51
 
66
- # Work in temporary directory to avoid modifying original
67
52
  with tempfile.TemporaryDirectory() as temp_dir:
68
53
  temp_content_dir = Path(temp_dir) / "content"
69
54
  shutil.copytree(input_dir, temp_content_dir)
70
55
 
71
- # Process XML files to remove pretty-printing whitespace
72
56
  for pattern in ["*.xml", "*.rels"]:
73
57
  for xml_file in temp_content_dir.rglob(pattern):
74
58
  _condense_xml(xml_file)
75
59
 
76
- # Create final Office file as zip archive
77
60
  output_path.parent.mkdir(parents=True, exist_ok=True)
78
61
  with zipfile.ZipFile(output_path, "w", zipfile.ZIP_DEFLATED) as zf:
79
62
  for f in temp_content_dir.rglob("*"):
@@ -89,16 +72,10 @@ def _run_validation(
89
72
  suffix: str,
90
73
  infer_author_func=None,
91
74
  ) -> tuple[bool, str | None]:
92
- """Run validation with auto-repair.
93
-
94
- Returns:
95
- (success, output) - success is True if all validations pass
96
- """
97
75
  output_lines = []
98
76
  validators = []
99
77
 
100
78
  if suffix == ".docx":
101
- # Infer author for redlining validation
102
79
  author = "Claude"
103
80
  if infer_author_func:
104
81
  try:
@@ -112,17 +89,14 @@ def _run_validation(
112
89
  ]
113
90
  elif suffix == ".pptx":
114
91
  validators = [PPTXSchemaValidator(unpacked_dir, original_file)]
115
- # xlsx has no schema validator yet
116
92
 
117
93
  if not validators:
118
94
  return True, None
119
95
 
120
- # Run auto-repair
121
96
  total_repairs = sum(v.repair() for v in validators)
122
97
  if total_repairs:
123
98
  output_lines.append(f"Auto-repaired {total_repairs} issue(s)")
124
99
 
125
- # Run validation
126
100
  success = all(v.validate() for v in validators)
127
101
 
128
102
  if success:
@@ -132,18 +106,14 @@ def _run_validation(
132
106
 
133
107
 
134
108
  def _condense_xml(xml_file: Path) -> None:
135
- """Strip unnecessary whitespace and remove comments from XML."""
136
109
  try:
137
110
  with open(xml_file, encoding="utf-8") as f:
138
111
  dom = defusedxml.minidom.parse(f)
139
112
 
140
- # Process each element to remove whitespace and comments
141
113
  for element in dom.getElementsByTagName("*"):
142
- # Skip text elements (w:t, a:t, etc.) - preserve their content
143
114
  if element.tagName.endswith(":t"):
144
115
  continue
145
116
 
146
- # Remove whitespace-only text nodes and comment nodes
147
117
  for child in list(element.childNodes):
148
118
  if (
149
119
  child.nodeType == child.TEXT_NODE