oxml_maker 0.1.1 → 0.1.3
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.
- checksums.yaml +4 -4
- data/.vscode/extensions.json +5 -0
- data/.vscode/settings.json +28 -0
- data/CHANGELOG.md +35 -0
- data/README.md +262 -20
- data/Rakefile +49 -0
- data/lib/oxml_maker/docx/word/document.xml +197 -5
- data/lib/oxml_maker/version.rb +1 -1
- metadata +7 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 244909709648e421faeca989cd00ef0d58f3de0917b606c36581059781cee835
|
|
4
|
+
data.tar.gz: cabce2d33245226176e2df74efb63a6fc9ae67edbd0f3a660da01dc017dd0996
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a3ce1886f3d9ef3a8d466e6979f505581bc6b211fd941b28b8bb975dec39f1c8eee90efc1a23919e64d9a9509ab9124644c0a887d9e4c2d182543978bcd1add1
|
|
7
|
+
data.tar.gz: b015b2ef222fe7c4485fd5be0d2c8751bbea8bd3eb98a4151a20910f64e352ce3ee3d26b5dfe44c2f63c406821eb8a92c9a94d5ff59288b21047d1d1940ec0ed
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"xml.format.enabled": true,
|
|
3
|
+
"xml.format.splitAttributes": "preserve",
|
|
4
|
+
"xml.format.joinCDATALines": false,
|
|
5
|
+
"xml.format.joinCommentLines": false,
|
|
6
|
+
"xml.format.joinContentLines": false,
|
|
7
|
+
"xml.format.spaceBeforeEmptyCloseTag": true,
|
|
8
|
+
"xml.format.splitAttributesIndentSize": 2,
|
|
9
|
+
"xml.format.maxLineWidth": 120,
|
|
10
|
+
"xml.format.preservedNewlines": 2,
|
|
11
|
+
"xml.preferences.includeSchemaLocation": "onValidationError",
|
|
12
|
+
"xml.validation.enabled": true,
|
|
13
|
+
"xml.validation.namespaces.enabled": "always",
|
|
14
|
+
"[xml]": {
|
|
15
|
+
"editor.formatOnSave": true,
|
|
16
|
+
"editor.insertSpaces": true,
|
|
17
|
+
"editor.tabSize": 2,
|
|
18
|
+
"editor.indentSize": 2,
|
|
19
|
+
"editor.wordWrap": "on",
|
|
20
|
+
"editor.defaultFormatter": "redhat.vscode-xml"
|
|
21
|
+
},
|
|
22
|
+
"files.associations": {
|
|
23
|
+
"*.xml": "xml"
|
|
24
|
+
},
|
|
25
|
+
"emmet.includeLanguages": {
|
|
26
|
+
"xml": "html"
|
|
27
|
+
}
|
|
28
|
+
}
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,40 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.1.3] - 2025-10-21
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- VS Code development environment configuration
|
|
7
|
+
- `.vscode/settings.json` with XML formatting rules and auto-format on save
|
|
8
|
+
- `.vscode/extensions.json` with recommended XML language support extensions
|
|
9
|
+
- Automatic test artifact cleanup functionality
|
|
10
|
+
- Enhanced development documentation in README
|
|
11
|
+
|
|
12
|
+
### Enhanced
|
|
13
|
+
- XML template files properly formatted with consistent indentation
|
|
14
|
+
- Development workflow with automatic cleanup of `.docx` and `.zip` files
|
|
15
|
+
- Contributor onboarding experience with VS Code integration
|
|
16
|
+
- Documentation structure for better developer experience
|
|
17
|
+
|
|
18
|
+
### Developer Experience
|
|
19
|
+
- Cross-platform XML formatting without additional gem dependencies
|
|
20
|
+
- Automatic cleanup of test artifacts from `lib/`, `public/`, and root directories
|
|
21
|
+
- Consistent 2-space indentation for XML files matching Ruby code style
|
|
22
|
+
- Real-time XML validation and IntelliSense support in VS Code
|
|
23
|
+
|
|
24
|
+
## [0.1.2] - 2025-10-21
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
- Advanced table features: `v_merge` and `new_line` functionality
|
|
28
|
+
- Comprehensive test suite for advanced table features (4 new tests)
|
|
29
|
+
- Support for vertical cell merging in tables
|
|
30
|
+
- Multi-line cell content with comma-separated value splitting
|
|
31
|
+
- Test coverage for complex table scenarios with real-world data examples
|
|
32
|
+
|
|
33
|
+
### Enhanced
|
|
34
|
+
- Table functionality with advanced formatting capabilities
|
|
35
|
+
- Test suite expanded to 67 tests with 344 assertions
|
|
36
|
+
- Documentation of table feature limitations and implementation details
|
|
37
|
+
|
|
3
38
|
## [0.1.1] - 2025-10-20
|
|
4
39
|
|
|
5
40
|
### Added
|
data/README.md
CHANGED
|
@@ -6,6 +6,7 @@ A Ruby gem for generating Microsoft Word DOCX files using OpenXML. Create profes
|
|
|
6
6
|
|
|
7
7
|
- ✅ **Generate Valid DOCX Files**: Creates Microsoft Word-compatible documents
|
|
8
8
|
- ✅ **Tables with Dynamic Data**: Populate tables from Ruby objects
|
|
9
|
+
- ✅ **Advanced Table Features**: Vertical cell merging (v_merge) and multi-line content (new_line)
|
|
9
10
|
- ✅ **Paragraphs and Text**: Simple text content with proper XML structure
|
|
10
11
|
- ✅ **Page Configuration**: Control page size, margins, headers/footers
|
|
11
12
|
- ✅ **Rails Integration**: Automatically detects Rails environment for file placement
|
|
@@ -124,6 +125,46 @@ params = {
|
|
|
124
125
|
}
|
|
125
126
|
```
|
|
126
127
|
|
|
128
|
+
### Advanced Table Features
|
|
129
|
+
|
|
130
|
+
#### Vertical Cell Merging and Multi-line Content
|
|
131
|
+
|
|
132
|
+
```ruby
|
|
133
|
+
# Advanced table with v_merge and new_line features
|
|
134
|
+
advanced_table = {
|
|
135
|
+
columns: [
|
|
136
|
+
{ name: "Category", width: 1500 },
|
|
137
|
+
{ name: "Items", width: 3000 }
|
|
138
|
+
],
|
|
139
|
+
rows: [
|
|
140
|
+
{
|
|
141
|
+
cells: [
|
|
142
|
+
{ value: :category, width: 1500, v_merge: true },
|
|
143
|
+
{ value: :items, width: 3000, new_line: true }
|
|
144
|
+
]
|
|
145
|
+
}
|
|
146
|
+
],
|
|
147
|
+
data: {
|
|
148
|
+
0 => [
|
|
149
|
+
OpenStruct.new(category: "Electronics", items: "iPhone, Samsung, Google"),
|
|
150
|
+
OpenStruct.new(category: "Electronics", items: "MacBook, ThinkPad, Dell"),
|
|
151
|
+
OpenStruct.new(category: "Books", items: "Fiction, Non-fiction, Science")
|
|
152
|
+
]
|
|
153
|
+
},
|
|
154
|
+
font_size: 12
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
# v_merge: true - Merges cells with same values vertically
|
|
158
|
+
# new_line: true - Splits comma-separated values into separate lines
|
|
159
|
+
params = {
|
|
160
|
+
sections: [
|
|
161
|
+
{ table: advanced_table }
|
|
162
|
+
],
|
|
163
|
+
page_size: { width: 12240, height: 15840 },
|
|
164
|
+
page_margin: { top: 1440, right: 1440, bottom: 1440, left: 1440, header: 720, footer: 720, gutter: 0 }
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
127
168
|
### Adding Paragraphs
|
|
128
169
|
|
|
129
170
|
Simple text content with proper XML formatting:
|
|
@@ -150,10 +191,227 @@ The gem intelligently handles output location:
|
|
|
150
191
|
|
|
151
192
|
## Development
|
|
152
193
|
|
|
194
|
+
### Setup
|
|
195
|
+
|
|
153
196
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
154
197
|
|
|
155
198
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
156
199
|
|
|
200
|
+
### 🔧 VS Code Setup for XML Development
|
|
201
|
+
|
|
202
|
+
**Important for Contributors**: This project includes XML template files that benefit from proper formatting and validation.
|
|
203
|
+
|
|
204
|
+
📖 **See [DEVELOPMENT.md](DEVELOPMENT.md) for detailed contributor guidelines and XML formatting standards.**
|
|
205
|
+
|
|
206
|
+
#### Recommended VS Code Extensions
|
|
207
|
+
|
|
208
|
+
When you open this project in VS Code, you'll be prompted to install recommended extensions:
|
|
209
|
+
|
|
210
|
+
- **XML Language Support** (`redhat.vscode-xml`) - Provides XML formatting, validation, and IntelliSense
|
|
211
|
+
- **JSON Language Features** (`ms-vscode.vscode-json`) - Enhanced JSON editing for configuration files
|
|
212
|
+
|
|
213
|
+
#### Automatic Configuration
|
|
214
|
+
|
|
215
|
+
The project includes `.vscode/settings.json` with pre-configured XML formatting rules:
|
|
216
|
+
|
|
217
|
+
- ✅ **Auto-format on save** for XML files
|
|
218
|
+
- ✅ **2-space indentation** (consistent with Ruby code)
|
|
219
|
+
- ✅ **Line width limit** of 120 characters
|
|
220
|
+
- ✅ **XML validation** enabled
|
|
221
|
+
- ✅ **Attribute splitting** for better readability
|
|
222
|
+
|
|
223
|
+
#### XML File Formatting
|
|
224
|
+
|
|
225
|
+
To format XML files manually:
|
|
226
|
+
1. Open any `.xml` file in `lib/oxml_maker/docx/`
|
|
227
|
+
2. Press `Shift+Alt+F` (or `Cmd+Shift+P` → "Format Document")
|
|
228
|
+
3. Files will auto-format on save when configured
|
|
229
|
+
|
|
230
|
+
This ensures consistent XML formatting across all contributors without additional gem dependencies! 🎨
|
|
231
|
+
|
|
232
|
+
### 📁 Project Structure
|
|
233
|
+
|
|
234
|
+
```
|
|
235
|
+
lib/oxml_maker/docx/ # XML template files - keep these formatted!
|
|
236
|
+
├── [Content_Types].xml
|
|
237
|
+
├── _rels/
|
|
238
|
+
└── word/
|
|
239
|
+
└── document.xml # Main document template
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### 🧹 Development Cleanup
|
|
243
|
+
|
|
244
|
+
The project includes automatic cleanup of test artifacts:
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
# Run tests with automatic cleanup
|
|
248
|
+
bundle exec rake test_clean
|
|
249
|
+
|
|
250
|
+
# Manual cleanup of .docx and .zip files
|
|
251
|
+
bundle exec rake clean
|
|
252
|
+
|
|
253
|
+
# Regular test run (includes automatic cleanup)
|
|
254
|
+
bundle exec rake test
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Test artifacts are automatically removed from:
|
|
258
|
+
- `lib/oxml_maker/` directory
|
|
259
|
+
- `public/` directory
|
|
260
|
+
- Root directory
|
|
261
|
+
|
|
262
|
+
This keeps your workspace clean during development! ✨
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
## Why OxmlMaker is Different: The Ruby Object Revolution
|
|
266
|
+
|
|
267
|
+
### The Problem with Traditional DOCX Gems
|
|
268
|
+
|
|
269
|
+
Most Ruby DOCX libraries force you into rigid patterns:
|
|
270
|
+
|
|
271
|
+
```ruby
|
|
272
|
+
# Traditional approach - manual, inflexible
|
|
273
|
+
builder.table do |t|
|
|
274
|
+
t.row ["Name", "Age"] # Static arrays only
|
|
275
|
+
t.row ["John", "30"] # Manual string building
|
|
276
|
+
t.row ["Jane", "25"] # Can't use objects directly
|
|
277
|
+
end
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### OxmlMaker's Revolutionary Approach
|
|
281
|
+
|
|
282
|
+
**Direct Ruby Object Mapping** - Use ANY Ruby object with methods:
|
|
283
|
+
|
|
284
|
+
```ruby
|
|
285
|
+
# Revolutionary - works with ANY objects!
|
|
286
|
+
data: {
|
|
287
|
+
0 => [
|
|
288
|
+
OpenStruct.new(name: "John", age: 30), # OpenStruct
|
|
289
|
+
User.find(1), # ActiveRecord model
|
|
290
|
+
JSON.parse('{"name": "Jane"}'), # JSON object
|
|
291
|
+
api_response.data, # API response
|
|
292
|
+
custom_object # Any object with methods
|
|
293
|
+
]
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
# Table automatically calls methods dynamically
|
|
297
|
+
{ value: :name } # Calls object.name on each object
|
|
298
|
+
{ value: :email } # Calls object.email on each object
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Perfect for Modern Architectures
|
|
302
|
+
|
|
303
|
+
#### 1. **JSON-Native Design**
|
|
304
|
+
Built for API-first and headless architectures:
|
|
305
|
+
|
|
306
|
+
```ruby
|
|
307
|
+
# HTML → JSON → DOCX pipeline
|
|
308
|
+
html_content = "<div><h1>Title</h1><table>...</table></div>"
|
|
309
|
+
json_data = html_to_json_parser(html_content)
|
|
310
|
+
|
|
311
|
+
# Direct consumption - no transformation needed!
|
|
312
|
+
doc = OxmlMaker::Document.new(
|
|
313
|
+
filename: "converted.docx",
|
|
314
|
+
params: json_data # Pure JSON input
|
|
315
|
+
)
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
#### 2. **Polymorphic Data Handling**
|
|
319
|
+
Mix any data sources in the same document:
|
|
320
|
+
|
|
321
|
+
```ruby
|
|
322
|
+
# Different object types in the same table!
|
|
323
|
+
data: {
|
|
324
|
+
0 => [
|
|
325
|
+
user_model, # ActiveRecord object
|
|
326
|
+
{ name: "Jane" }, # Hash
|
|
327
|
+
OpenStruct.new(name: "Bob"), # OpenStruct
|
|
328
|
+
json_api_response # JSON object
|
|
329
|
+
]
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
#### 3. **Configuration-Driven Architecture**
|
|
334
|
+
Documents are pure data structures - serializable and cacheable:
|
|
335
|
+
|
|
336
|
+
```ruby
|
|
337
|
+
# Store templates as JSON in database
|
|
338
|
+
template = DocumentTemplate.find_by(name: "invoice")
|
|
339
|
+
live_data = Invoice.includes(:line_items).find(params[:id])
|
|
340
|
+
|
|
341
|
+
# Merge template with live data
|
|
342
|
+
params = template.structure.deep_merge({
|
|
343
|
+
sections: [{
|
|
344
|
+
table: {
|
|
345
|
+
data: { 0 => live_data.line_items.to_a } # Direct AR relation!
|
|
346
|
+
}
|
|
347
|
+
}]
|
|
348
|
+
})
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### Comparison with Other Ruby DOCX Gems
|
|
352
|
+
|
|
353
|
+
| Feature | OxmlMaker | Caracal | ruby-docx | docx | sablon |
|
|
354
|
+
|---------|-----------|---------|-----------|------|--------|
|
|
355
|
+
| **Ruby Object Mapping** | ✅ Dynamic | ❌ Manual | ❌ Manual | ❌ Template | ❌ Template |
|
|
356
|
+
| **JSON Serializable** | ✅ 100% | ❌ Code-based | ❌ Code-based | ❌ Template | ❌ Template |
|
|
357
|
+
| **Any Ruby Object** | ✅ Polymorphic | ❌ Arrays only | ❌ Limited | ❌ Static | ❌ Mail merge |
|
|
358
|
+
| **HTML→JSON→DOCX** | ✅ Native | ❌ Complex | ❌ N/A | ❌ N/A | ❌ Template only |
|
|
359
|
+
| **API-Friendly** | ✅ Pure data | ❌ Code required | ❌ Code required | ❌ Files | ❌ Templates |
|
|
360
|
+
| **Microservices Ready** | ✅ Stateless | ❌ Complex | ❌ Complex | ❌ File-based | ❌ Template-based |
|
|
361
|
+
|
|
362
|
+
### Perfect Use Cases
|
|
363
|
+
|
|
364
|
+
#### **CMS/Blog Export**
|
|
365
|
+
```ruby
|
|
366
|
+
# Blog post with mixed content types
|
|
367
|
+
post_json = {
|
|
368
|
+
sections: [
|
|
369
|
+
{ paragraph: { text: post.title } },
|
|
370
|
+
{ table: {
|
|
371
|
+
data: { 0 => post.comments.approved } # Direct relation!
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
]
|
|
375
|
+
}
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
#### **API Report Generation**
|
|
379
|
+
```ruby
|
|
380
|
+
# Consume external APIs directly
|
|
381
|
+
api_response = HTTParty.get("https://api.example.com/reports/#{id}")
|
|
382
|
+
json_data = JSON.parse(api_response.body, object_class: OpenStruct)
|
|
383
|
+
|
|
384
|
+
# No transformation needed!
|
|
385
|
+
doc = OxmlMaker::Document.new(params: { sections: json_data.sections })
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
#### **Dynamic Form Processing**
|
|
389
|
+
```ruby
|
|
390
|
+
# Form submission → DOCX
|
|
391
|
+
form_data = params[:form_responses] # Frontend JSON
|
|
392
|
+
|
|
393
|
+
document_params = {
|
|
394
|
+
sections: [{
|
|
395
|
+
table: {
|
|
396
|
+
data: { 0 => form_data.map { |item| OpenStruct.new(item) } }
|
|
397
|
+
}
|
|
398
|
+
}]
|
|
399
|
+
}
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
### The Architectural Advantage
|
|
403
|
+
|
|
404
|
+
**Zero Impedance Mismatch** - Your data flows directly into documents without transformation layers, making OxmlMaker perfect for:
|
|
405
|
+
|
|
406
|
+
- **Headless CMS** systems
|
|
407
|
+
- **API-first** applications
|
|
408
|
+
- **Microservice** architectures
|
|
409
|
+
- **HTML→DOCX** conversion pipelines
|
|
410
|
+
- **Real-time report** generation
|
|
411
|
+
- **JSON-driven** document templates
|
|
412
|
+
|
|
413
|
+
This isn't just a different API - it's a **fundamentally superior architecture** for modern Ruby applications.
|
|
414
|
+
|
|
157
415
|
## Testing
|
|
158
416
|
|
|
159
417
|
### Test Framework
|
|
@@ -166,9 +424,10 @@ The gem uses **Minitest** as its testing framework, which is included in Ruby's
|
|
|
166
424
|
|
|
167
425
|
### Current Test Coverage
|
|
168
426
|
|
|
169
|
-
- **
|
|
427
|
+
- **67 tests, 344 assertions, 0 failures, 0 errors**
|
|
170
428
|
- Unit tests for all classes (Document, Paragraph, Table)
|
|
171
429
|
- Integration tests for complete workflows
|
|
430
|
+
- Advanced table feature tests (v_merge, new_line)
|
|
172
431
|
- ZIP functionality tests with rubyzip
|
|
173
432
|
- Rails environment detection tests
|
|
174
433
|
- Error handling and edge case tests
|
|
@@ -259,23 +518,6 @@ def test_created_zip_is_valid_docx
|
|
|
259
518
|
end
|
|
260
519
|
```
|
|
261
520
|
|
|
262
|
-
### Testing Best Practices
|
|
263
|
-
|
|
264
|
-
1. **Use Setup and Teardown** for consistent test environments
|
|
265
|
-
2. **Test Edge Cases** including empty inputs, nil values, and special characters
|
|
266
|
-
3. **Use Descriptive Test Names** that explain what is being tested
|
|
267
|
-
4. **Test Both Success and Failure Paths** to ensure robust error handling
|
|
268
|
-
5. **Mock External Dependencies** when needed (Rails environment, file systems)
|
|
269
|
-
|
|
270
|
-
### Common Assertions
|
|
271
|
-
|
|
272
|
-
- `assert_equal expected, actual` - Test equality
|
|
273
|
-
- `assert_includes collection, item` - Test inclusion
|
|
274
|
-
- `assert_raises(ExceptionClass) { code }` - Test exceptions
|
|
275
|
-
- `assert condition` - Test truthiness
|
|
276
|
-
- `refute condition` - Test falsiness
|
|
277
|
-
- `assert_kind_of Class, object` - Test object type
|
|
278
|
-
|
|
279
521
|
## Dependencies
|
|
280
522
|
|
|
281
523
|
- **rubyzip (~> 3.2)** - For ZIP file creation and DOCX generation
|
|
@@ -284,7 +526,7 @@ end
|
|
|
284
526
|
|
|
285
527
|
## Contributing
|
|
286
528
|
|
|
287
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
|
529
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/airbearr/oxml_maker. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/airbearr/oxml_maker/blob/master/CODE_OF_CONDUCT.md).
|
|
288
530
|
|
|
289
531
|
## License
|
|
290
532
|
|
|
@@ -292,4 +534,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
|
292
534
|
|
|
293
535
|
## Code of Conduct
|
|
294
536
|
|
|
295
|
-
Everyone interacting in the OxmlMaker project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/
|
|
537
|
+
Everyone interacting in the OxmlMaker project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/airbearr/oxml_maker/blob/master/CODE_OF_CONDUCT.md).
|
data/Rakefile
CHANGED
|
@@ -9,4 +9,53 @@ require "rubocop/rake_task"
|
|
|
9
9
|
|
|
10
10
|
RuboCop::RakeTask.new
|
|
11
11
|
|
|
12
|
+
# Cleanup tasks
|
|
13
|
+
desc "Clean up test artifacts (docx and zip files)"
|
|
14
|
+
task :clean do
|
|
15
|
+
require "fileutils"
|
|
16
|
+
|
|
17
|
+
puts "Cleaning up test artifacts..."
|
|
18
|
+
|
|
19
|
+
# Clean up public directory
|
|
20
|
+
public_dir = File.join(Dir.pwd, "public")
|
|
21
|
+
if Dir.exist?(public_dir)
|
|
22
|
+
docx_files = Dir.glob(File.join(public_dir, "*.docx"))
|
|
23
|
+
zip_files = Dir.glob(File.join(public_dir, "*.zip"))
|
|
24
|
+
|
|
25
|
+
docx_files.each { |f| FileUtils.rm_f(f) }
|
|
26
|
+
zip_files.each { |f| FileUtils.rm_f(f) }
|
|
27
|
+
|
|
28
|
+
removed_count = docx_files.length + zip_files.length
|
|
29
|
+
puts "Removed #{removed_count} files from public directory" if removed_count > 0
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Clean up lib/oxml_maker directory
|
|
33
|
+
lib_dir = File.join(Dir.pwd, "lib", "oxml_maker")
|
|
34
|
+
if Dir.exist?(lib_dir)
|
|
35
|
+
lib_docx_files = Dir.glob(File.join(lib_dir, "*.docx"))
|
|
36
|
+
lib_zip_files = Dir.glob(File.join(lib_dir, "*.zip"))
|
|
37
|
+
|
|
38
|
+
lib_docx_files.each { |f| FileUtils.rm_f(f) }
|
|
39
|
+
lib_zip_files.each { |f| FileUtils.rm_f(f) }
|
|
40
|
+
|
|
41
|
+
lib_removed_count = lib_docx_files.length + lib_zip_files.length
|
|
42
|
+
puts "Removed #{lib_removed_count} files from lib/oxml_maker directory" if lib_removed_count > 0
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Clean up root directory
|
|
46
|
+
root_docx = Dir.glob("*.docx")
|
|
47
|
+
root_zip = Dir.glob("*.zip")
|
|
48
|
+
|
|
49
|
+
root_docx.each { |f| FileUtils.rm_f(f) }
|
|
50
|
+
root_zip.each { |f| FileUtils.rm_f(f) }
|
|
51
|
+
|
|
52
|
+
root_removed = root_docx.length + root_zip.length
|
|
53
|
+
puts "Removed #{root_removed} files from root directory" if root_removed > 0
|
|
54
|
+
|
|
55
|
+
puts "Cleanup completed!"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
desc "Run tests with automatic cleanup"
|
|
59
|
+
task test_clean: %i[clean test clean]
|
|
60
|
+
|
|
12
61
|
task default: %i[test rubocop]
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<w:body>
|
|
4
4
|
<w:p>
|
|
5
5
|
<w:r>
|
|
6
|
-
<w:t>
|
|
6
|
+
<w:t>Document Title - Integration Test</w:t>
|
|
7
7
|
</w:r>
|
|
8
8
|
</w:p>
|
|
9
9
|
|
|
@@ -25,6 +25,8 @@
|
|
|
25
25
|
</w:tblPr>
|
|
26
26
|
<w:tblGrid>
|
|
27
27
|
<w:gridCol w:w="3000"/>
|
|
28
|
+
<w:gridCol w:w="2000"/>
|
|
29
|
+
<w:gridCol w:w="1500"/>
|
|
28
30
|
</w:tblGrid>
|
|
29
31
|
<w:tr>
|
|
30
32
|
<w:tblPrEx>
|
|
@@ -50,9 +52,51 @@
|
|
|
50
52
|
<w:r>
|
|
51
53
|
<w:rPr>
|
|
52
54
|
<w:b/>
|
|
53
|
-
<w:sz w:val="
|
|
55
|
+
<w:sz w:val="24"/>
|
|
54
56
|
</w:rPr>
|
|
55
|
-
<w:t>
|
|
57
|
+
<w:t>Product</w:t>
|
|
58
|
+
</w:r>
|
|
59
|
+
</w:p>
|
|
60
|
+
</w:tc>
|
|
61
|
+
|
|
62
|
+
<w:tc>
|
|
63
|
+
<w:tcPr>
|
|
64
|
+
<w:tcW w:w="2000"/>
|
|
65
|
+
</w:tcPr>
|
|
66
|
+
<w:p>
|
|
67
|
+
<w:pPr>
|
|
68
|
+
<w:jc w:val="center"/>
|
|
69
|
+
<w:rPr>
|
|
70
|
+
<w:b/>
|
|
71
|
+
</w:rPr>
|
|
72
|
+
</w:pPr>
|
|
73
|
+
<w:r>
|
|
74
|
+
<w:rPr>
|
|
75
|
+
<w:b/>
|
|
76
|
+
<w:sz w:val="24"/>
|
|
77
|
+
</w:rPr>
|
|
78
|
+
<w:t>Price</w:t>
|
|
79
|
+
</w:r>
|
|
80
|
+
</w:p>
|
|
81
|
+
</w:tc>
|
|
82
|
+
|
|
83
|
+
<w:tc>
|
|
84
|
+
<w:tcPr>
|
|
85
|
+
<w:tcW w:w="1500"/>
|
|
86
|
+
</w:tcPr>
|
|
87
|
+
<w:p>
|
|
88
|
+
<w:pPr>
|
|
89
|
+
<w:jc w:val="center"/>
|
|
90
|
+
<w:rPr>
|
|
91
|
+
<w:b/>
|
|
92
|
+
</w:rPr>
|
|
93
|
+
</w:pPr>
|
|
94
|
+
<w:r>
|
|
95
|
+
<w:rPr>
|
|
96
|
+
<w:b/>
|
|
97
|
+
<w:sz w:val="24"/>
|
|
98
|
+
</w:rPr>
|
|
99
|
+
<w:t>Quantity</w:t>
|
|
56
100
|
</w:r>
|
|
57
101
|
</w:p>
|
|
58
102
|
</w:tc>
|
|
@@ -70,8 +114,150 @@
|
|
|
70
114
|
<w:jc w:val='center'/>
|
|
71
115
|
</w:pPr>
|
|
72
116
|
<w:r>
|
|
73
|
-
<w:rPr><w:sz w:val='
|
|
74
|
-
<w:t>
|
|
117
|
+
<w:rPr><w:sz w:val='24'/></w:rPr>
|
|
118
|
+
<w:t>Widget A</w:t>
|
|
119
|
+
</w:r>
|
|
120
|
+
</w:p>
|
|
121
|
+
</w:tc>
|
|
122
|
+
|
|
123
|
+
<w:tc>
|
|
124
|
+
<w:tcPr>
|
|
125
|
+
<w:tcW w:w='2000' w:type='dxa'/>
|
|
126
|
+
|
|
127
|
+
<w:vAlign w:val="center"/>
|
|
128
|
+
</w:tcPr>
|
|
129
|
+
<w:p>
|
|
130
|
+
<w:pPr>
|
|
131
|
+
<w:jc w:val='center'/>
|
|
132
|
+
</w:pPr>
|
|
133
|
+
<w:r>
|
|
134
|
+
<w:rPr><w:sz w:val='24'/></w:rPr>
|
|
135
|
+
<w:t>$10.99</w:t>
|
|
136
|
+
</w:r>
|
|
137
|
+
</w:p>
|
|
138
|
+
</w:tc>
|
|
139
|
+
|
|
140
|
+
<w:tc>
|
|
141
|
+
<w:tcPr>
|
|
142
|
+
<w:tcW w:w='1500' w:type='dxa'/>
|
|
143
|
+
|
|
144
|
+
<w:vAlign w:val="center"/>
|
|
145
|
+
</w:tcPr>
|
|
146
|
+
<w:p>
|
|
147
|
+
<w:pPr>
|
|
148
|
+
<w:jc w:val='center'/>
|
|
149
|
+
</w:pPr>
|
|
150
|
+
<w:r>
|
|
151
|
+
<w:rPr><w:sz w:val='24'/></w:rPr>
|
|
152
|
+
<w:t>5</w:t>
|
|
153
|
+
</w:r>
|
|
154
|
+
</w:p>
|
|
155
|
+
</w:tc>
|
|
156
|
+
|
|
157
|
+
</w:tr>
|
|
158
|
+
|
|
159
|
+
<w:tr>
|
|
160
|
+
<w:tc>
|
|
161
|
+
<w:tcPr>
|
|
162
|
+
<w:tcW w:w='3000' w:type='dxa'/>
|
|
163
|
+
|
|
164
|
+
<w:vAlign w:val="center"/>
|
|
165
|
+
</w:tcPr>
|
|
166
|
+
<w:p>
|
|
167
|
+
<w:pPr>
|
|
168
|
+
<w:jc w:val='center'/>
|
|
169
|
+
</w:pPr>
|
|
170
|
+
<w:r>
|
|
171
|
+
<w:rPr><w:sz w:val='24'/></w:rPr>
|
|
172
|
+
<w:t>Gadget B</w:t>
|
|
173
|
+
</w:r>
|
|
174
|
+
</w:p>
|
|
175
|
+
</w:tc>
|
|
176
|
+
|
|
177
|
+
<w:tc>
|
|
178
|
+
<w:tcPr>
|
|
179
|
+
<w:tcW w:w='2000' w:type='dxa'/>
|
|
180
|
+
|
|
181
|
+
<w:vAlign w:val="center"/>
|
|
182
|
+
</w:tcPr>
|
|
183
|
+
<w:p>
|
|
184
|
+
<w:pPr>
|
|
185
|
+
<w:jc w:val='center'/>
|
|
186
|
+
</w:pPr>
|
|
187
|
+
<w:r>
|
|
188
|
+
<w:rPr><w:sz w:val='24'/></w:rPr>
|
|
189
|
+
<w:t>$25.50</w:t>
|
|
190
|
+
</w:r>
|
|
191
|
+
</w:p>
|
|
192
|
+
</w:tc>
|
|
193
|
+
|
|
194
|
+
<w:tc>
|
|
195
|
+
<w:tcPr>
|
|
196
|
+
<w:tcW w:w='1500' w:type='dxa'/>
|
|
197
|
+
|
|
198
|
+
<w:vAlign w:val="center"/>
|
|
199
|
+
</w:tcPr>
|
|
200
|
+
<w:p>
|
|
201
|
+
<w:pPr>
|
|
202
|
+
<w:jc w:val='center'/>
|
|
203
|
+
</w:pPr>
|
|
204
|
+
<w:r>
|
|
205
|
+
<w:rPr><w:sz w:val='24'/></w:rPr>
|
|
206
|
+
<w:t>3</w:t>
|
|
207
|
+
</w:r>
|
|
208
|
+
</w:p>
|
|
209
|
+
</w:tc>
|
|
210
|
+
|
|
211
|
+
</w:tr>
|
|
212
|
+
|
|
213
|
+
<w:tr>
|
|
214
|
+
<w:tc>
|
|
215
|
+
<w:tcPr>
|
|
216
|
+
<w:tcW w:w='3000' w:type='dxa'/>
|
|
217
|
+
|
|
218
|
+
<w:vAlign w:val="center"/>
|
|
219
|
+
</w:tcPr>
|
|
220
|
+
<w:p>
|
|
221
|
+
<w:pPr>
|
|
222
|
+
<w:jc w:val='center'/>
|
|
223
|
+
</w:pPr>
|
|
224
|
+
<w:r>
|
|
225
|
+
<w:rPr><w:sz w:val='24'/></w:rPr>
|
|
226
|
+
<w:t>Tool C</w:t>
|
|
227
|
+
</w:r>
|
|
228
|
+
</w:p>
|
|
229
|
+
</w:tc>
|
|
230
|
+
|
|
231
|
+
<w:tc>
|
|
232
|
+
<w:tcPr>
|
|
233
|
+
<w:tcW w:w='2000' w:type='dxa'/>
|
|
234
|
+
|
|
235
|
+
<w:vAlign w:val="center"/>
|
|
236
|
+
</w:tcPr>
|
|
237
|
+
<w:p>
|
|
238
|
+
<w:pPr>
|
|
239
|
+
<w:jc w:val='center'/>
|
|
240
|
+
</w:pPr>
|
|
241
|
+
<w:r>
|
|
242
|
+
<w:rPr><w:sz w:val='24'/></w:rPr>
|
|
243
|
+
<w:t>$45.00</w:t>
|
|
244
|
+
</w:r>
|
|
245
|
+
</w:p>
|
|
246
|
+
</w:tc>
|
|
247
|
+
|
|
248
|
+
<w:tc>
|
|
249
|
+
<w:tcPr>
|
|
250
|
+
<w:tcW w:w='1500' w:type='dxa'/>
|
|
251
|
+
|
|
252
|
+
<w:vAlign w:val="center"/>
|
|
253
|
+
</w:tcPr>
|
|
254
|
+
<w:p>
|
|
255
|
+
<w:pPr>
|
|
256
|
+
<w:jc w:val='center'/>
|
|
257
|
+
</w:pPr>
|
|
258
|
+
<w:r>
|
|
259
|
+
<w:rPr><w:sz w:val='24'/></w:rPr>
|
|
260
|
+
<w:t>1</w:t>
|
|
75
261
|
</w:r>
|
|
76
262
|
</w:p>
|
|
77
263
|
</w:tc>
|
|
@@ -80,6 +266,12 @@
|
|
|
80
266
|
|
|
81
267
|
</w:tbl>
|
|
82
268
|
|
|
269
|
+
<w:p>
|
|
270
|
+
<w:r>
|
|
271
|
+
<w:t>End of Report</w:t>
|
|
272
|
+
</w:r>
|
|
273
|
+
</w:p>
|
|
274
|
+
|
|
83
275
|
<w:sectPr>
|
|
84
276
|
<w:pgSz w:w='12240' w:h='15840'/>
|
|
85
277
|
<w:pgMar w:top='1440' w:right='1440' w:bottom='1440' w:left='1440' w:header='720' w:footer='720' w:gutter='0'/>
|
data/lib/oxml_maker/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: oxml_maker
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- airbearr
|
|
@@ -33,6 +33,8 @@ extensions: []
|
|
|
33
33
|
extra_rdoc_files: []
|
|
34
34
|
files:
|
|
35
35
|
- ".rubocop.yml"
|
|
36
|
+
- ".vscode/extensions.json"
|
|
37
|
+
- ".vscode/settings.json"
|
|
36
38
|
- CHANGELOG.md
|
|
37
39
|
- CODE_OF_CONDUCT.md
|
|
38
40
|
- LICENSE.txt
|
|
@@ -47,14 +49,14 @@ files:
|
|
|
47
49
|
- lib/oxml_maker/table.rb
|
|
48
50
|
- lib/oxml_maker/version.rb
|
|
49
51
|
- sig/oxml_maker.rbs
|
|
50
|
-
homepage: https://github.com/
|
|
52
|
+
homepage: https://github.com/airbearr/oxml_maker
|
|
51
53
|
licenses:
|
|
52
54
|
- MIT
|
|
53
55
|
metadata:
|
|
54
56
|
allowed_push_host: https://rubygems.org
|
|
55
|
-
homepage_uri: https://github.com/
|
|
56
|
-
source_code_uri: https://github.com/
|
|
57
|
-
changelog_uri: https://github.com/
|
|
57
|
+
homepage_uri: https://github.com/airbearr/oxml_maker
|
|
58
|
+
source_code_uri: https://github.com/airbearr/oxml_maker
|
|
59
|
+
changelog_uri: https://github.com/airbearr/oxml_maker/blob/main/CHANGELOG.md
|
|
58
60
|
rubygems_mfa_required: 'true'
|
|
59
61
|
rdoc_options: []
|
|
60
62
|
require_paths:
|