uniword 1.2.5 → 1.3.0
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/CHANGELOG.md +223 -0
- data/CONTRIBUTING.md +1 -1
- data/config/ooxml/schemas/shared_types.yml +5 -4
- data/data/schemas/ecma/dc.xsd +118 -0
- data/data/schemas/ecma/dcmitype.xsd +50 -0
- data/data/schemas/ecma/dcterms.xsd +331 -0
- data/data/schemas/ecma/opc-coreProperties.xsd +2 -2
- data/data/schemas/ecma/xml.xsd +117 -0
- data/lib/uniword/builder/bibliography_builder.rb +1 -1
- data/lib/uniword/builder/chart_builder.rb +19 -9
- data/lib/uniword/builder/comment_anchorer.rb +221 -0
- data/lib/uniword/builder/document_builder.rb +97 -6
- data/lib/uniword/builder/image_builder.rb +6 -5
- data/lib/uniword/builder/run_utils.rb +2 -0
- data/lib/uniword/builder.rb +1 -0
- data/lib/uniword/cli/fonts_cli.rb +52 -0
- data/lib/uniword/cli/main.rb +110 -11
- data/lib/uniword/cli/page_cli.rb +85 -0
- data/lib/uniword/cli/styles_cli.rb +204 -0
- data/lib/uniword/cli/theme_cli.rb +88 -0
- data/lib/uniword/cli/toc_cli.rb +22 -2
- data/lib/uniword/comment.rb +20 -15
- data/lib/uniword/comment_range.rb +3 -3
- data/lib/uniword/comments_part.rb +51 -19
- data/lib/uniword/configuration/configuration_loader.rb +5 -3
- data/lib/uniword/configuration.rb +93 -1
- data/lib/uniword/content_types.rb +19 -39
- data/lib/uniword/document_factory.rb +9 -1
- data/lib/uniword/document_writer.rb +16 -5
- data/lib/uniword/docx/chart_part.rb +34 -0
- data/lib/uniword/docx/custom_xml_item.rb +83 -0
- data/lib/uniword/docx/header_footer_part.rb +140 -0
- data/lib/uniword/docx/header_footer_part_collection.rb +135 -0
- data/lib/uniword/docx/header_footer_view.rb +225 -0
- data/lib/uniword/docx/id_allocator.rb +130 -36
- data/lib/uniword/docx/package.rb +223 -35
- data/lib/uniword/docx/package_defaults.rb +58 -78
- data/lib/uniword/docx/package_integrity_checker.rb +312 -0
- data/lib/uniword/docx/package_serialization.rb +103 -231
- data/lib/uniword/docx/part.rb +106 -0
- data/lib/uniword/docx/part_collection.rb +123 -0
- data/lib/uniword/docx/reconciler/body.rb +59 -68
- data/lib/uniword/docx/reconciler/fix.rb +46 -0
- data/lib/uniword/docx/reconciler/fix_codes.rb +37 -30
- data/lib/uniword/docx/reconciler/helpers.rb +9 -1
- data/lib/uniword/docx/reconciler/notes.rb +17 -8
- data/lib/uniword/docx/reconciler/package_structure.rb +169 -221
- data/lib/uniword/docx/reconciler/parts.rb +36 -13
- data/lib/uniword/docx/reconciler/referential_integrity.rb +297 -123
- data/lib/uniword/docx/reconciler/tables.rb +78 -16
- data/lib/uniword/docx/reconciler/theme.rb +7 -4
- data/lib/uniword/docx/reconciler.rb +36 -14
- data/lib/uniword/docx.rb +10 -0
- data/lib/uniword/drawingml/blip.rb +0 -1
- data/lib/uniword/drawingml/color_scheme.rb +5 -6
- data/lib/uniword/drawingml/font_scheme.rb +4 -8
- data/lib/uniword/drawingml/theme.rb +12 -6
- data/lib/uniword/errors.rb +8 -1
- data/lib/uniword/footer.rb +4 -0
- data/lib/uniword/header.rb +4 -0
- data/lib/uniword/hyperlink.rb +1 -1
- data/lib/uniword/image.rb +6 -6
- data/lib/uniword/lazy_loader.rb +1 -2
- data/lib/uniword/model_attribute_access.rb +20 -4
- data/lib/uniword/ooxml/dotx_package.rb +42 -2
- data/lib/uniword/ooxml/part_definition.rb +171 -0
- data/lib/uniword/ooxml/part_registry.rb +311 -0
- data/lib/uniword/ooxml/relationships/image_relationship.rb +1 -1
- data/lib/uniword/ooxml/relationships/package_relationships.rb +20 -22
- data/lib/uniword/ooxml/schema/element_serializer.rb +8 -7
- data/lib/uniword/ooxml/types/hex_color_value.rb +38 -0
- data/lib/uniword/ooxml/types/ooxml_boolean.rb +27 -14
- data/lib/uniword/ooxml/types/ooxml_boolean_optional.rb +21 -16
- data/lib/uniword/ooxml/types/theme_color_value.rb +22 -0
- data/lib/uniword/ooxml/types/unsigned_decimal_number.rb +30 -0
- data/lib/uniword/ooxml/types.rb +10 -0
- data/lib/uniword/ooxml.rb +2 -0
- data/lib/uniword/properties/alignment.rb +8 -3
- data/lib/uniword/properties/border.rb +52 -6
- data/lib/uniword/properties/cell_vertical_align.rb +4 -1
- data/lib/uniword/properties/color_value.rb +8 -3
- data/lib/uniword/properties/highlight.rb +9 -5
- data/lib/uniword/properties/shading.rb +4 -3
- data/lib/uniword/properties/tab_stop.rb +6 -1
- data/lib/uniword/properties/table_justification.rb +4 -1
- data/lib/uniword/properties/underline.rb +4 -2
- data/lib/uniword/properties/vertical_align.rb +6 -3
- data/lib/uniword/review/review_manager.rb +23 -9
- data/lib/uniword/revision.rb +9 -9
- data/lib/uniword/schema/model_generator.rb +31 -15
- data/lib/uniword/shared_types/hex_color.rb +4 -1
- data/lib/uniword/shared_types/pixel_measure.rb +4 -1
- data/lib/uniword/shared_types/point_measure.rb +4 -1
- data/lib/uniword/shared_types/text_alignment.rb +6 -1
- data/lib/uniword/shared_types/twips_measure.rb +4 -1
- data/lib/uniword/spreadsheetml/phonetic_pr.rb +1 -1
- data/lib/uniword/spreadsheetml/shared_string_table.rb +2 -2
- data/lib/uniword/spreadsheetml/table_formula.rb +1 -1
- data/lib/uniword/template/variable_resolver.rb +40 -7
- data/lib/uniword/themes/theme_transformation.rb +55 -41
- data/lib/uniword/toc/toc_generator.rb +2 -0
- data/lib/uniword/validation/engine.rb +35 -0
- data/lib/uniword/validation/link_checker.rb +1 -1
- data/lib/uniword/validation/opc_validator.rb +0 -1
- data/lib/uniword/validation/report/layer_result.rb +0 -1
- data/lib/uniword/validation/report/terminal_formatter.rb +0 -1
- data/lib/uniword/validation/report/verification_report.rb +0 -2
- data/lib/uniword/validation/report.rb +20 -0
- data/lib/uniword/validation/rules/base.rb +10 -2
- data/lib/uniword/validation/rules/bookmark_pairing_rule.rb +38 -0
- data/lib/uniword/validation/rules/bookmark_uniqueness_rule.rb +48 -0
- data/lib/uniword/validation/rules/bookmarks_rule.rb +0 -2
- data/lib/uniword/validation/rules/content_types_coverage_rule.rb +0 -2
- data/lib/uniword/validation/rules/core_properties_namespace_rule.rb +0 -2
- data/lib/uniword/validation/rules/document_body_rule.rb +25 -0
- data/lib/uniword/validation/rules/document_context.rb +7 -0
- data/lib/uniword/validation/rules/empty_paragraphs_rule.rb +27 -0
- data/lib/uniword/validation/rules/font_table_signature_rule.rb +0 -2
- data/lib/uniword/validation/rules/fonts_rule.rb +0 -2
- data/lib/uniword/validation/rules/footnotes_rule.rb +0 -2
- data/lib/uniword/validation/rules/headers_footers_rule.rb +0 -2
- data/lib/uniword/validation/rules/images_rule.rb +0 -2
- data/lib/uniword/validation/rules/mc_ignorable_namespace_rule.rb +0 -2
- data/lib/uniword/validation/rules/model_context.rb +32 -0
- data/lib/uniword/validation/rules/model_rule.rb +34 -0
- data/lib/uniword/validation/rules/numbering_preservation_rule.rb +0 -2
- data/lib/uniword/validation/rules/numbering_rule.rb +0 -2
- data/lib/uniword/validation/rules/relationship_integrity_rule.rb +0 -1
- data/lib/uniword/validation/rules/rsid_rule.rb +0 -2
- data/lib/uniword/validation/rules/section_properties_rule.rb +0 -2
- data/lib/uniword/validation/rules/settings_rule.rb +0 -2
- data/lib/uniword/validation/rules/settings_values_rule.rb +0 -2
- data/lib/uniword/validation/rules/style_references_rule.rb +0 -2
- data/lib/uniword/validation/rules/table_grid_rule.rb +27 -0
- data/lib/uniword/validation/rules/table_properties_rule.rb +27 -0
- data/lib/uniword/validation/rules/tables_rule.rb +0 -2
- data/lib/uniword/validation/rules/theme_completeness_rule.rb +0 -2
- data/lib/uniword/validation/rules/theme_rule.rb +0 -2
- data/lib/uniword/validation/rules.rb +61 -23
- data/lib/uniword/validation/schema_registry.rb +11 -0
- data/lib/uniword/validation/validators/document_semantics_validator.rb +1 -9
- data/lib/uniword/validation/validators/xml_schema_validator.rb +0 -2
- data/lib/uniword/validation/validators.rb +0 -9
- data/lib/uniword/validation/verify_orchestrator.rb +0 -7
- data/lib/uniword/validation.rb +7 -2
- data/lib/uniword/version.rb +1 -1
- data/lib/uniword/vml/imagedata.rb +0 -1
- data/lib/uniword/wordprocessingml/attached_template.rb +0 -1
- data/lib/uniword/wordprocessingml/deleted_text.rb +1 -1
- data/lib/uniword/wordprocessingml/document_root.rb +211 -21
- data/lib/uniword/wordprocessingml/endnotes.rb +4 -0
- data/lib/uniword/wordprocessingml/font_replacer.rb +147 -0
- data/lib/uniword/wordprocessingml/footnotes.rb +4 -0
- data/lib/uniword/wordprocessingml/hdr_shape_defaults.rb +0 -1
- data/lib/uniword/wordprocessingml/hyperlink.rb +0 -1
- data/lib/uniword/wordprocessingml/level.rb +6 -20
- data/lib/uniword/wordprocessingml/math_pr.rb +0 -11
- data/lib/uniword/wordprocessingml/numbering_definition.rb +16 -8
- data/lib/uniword/wordprocessingml/page_setup.rb +181 -0
- data/lib/uniword/wordprocessingml/paragraph_properties.rb +33 -28
- data/lib/uniword/wordprocessingml/rsids.rb +0 -2
- data/lib/uniword/wordprocessingml/run.rb +3 -0
- data/lib/uniword/wordprocessingml/section_properties.rb +2 -2
- data/lib/uniword/wordprocessingml/settings.rb +8 -34
- data/lib/uniword/wordprocessingml/shape_defaults.rb +0 -1
- data/lib/uniword/wordprocessingml/style.rb +2 -1
- data/lib/uniword/wordprocessingml/style_cleanup.rb +198 -0
- data/lib/uniword/wordprocessingml/table_cell_properties.rb +6 -6
- data/lib/uniword/wordprocessingml/update_fields.rb +27 -0
- data/lib/uniword/wordprocessingml/w14_attributes.rb +30 -2
- data/lib/uniword/wordprocessingml.rb +4 -0
- data/lib/uniword.rb +27 -2
- metadata +38 -19
- data/config/validation_rules.yml +0 -60
- data/config/warning_rules.yml +0 -57
- data/lib/uniword/validation/document_validator.rb +0 -272
- data/lib/uniword/validation/structural_validator.rb +0 -116
- data/lib/uniword/validation/validators/content_type_validator.rb +0 -165
- data/lib/uniword/validation/validators/file_structure_validator.rb +0 -104
- data/lib/uniword/validation/validators/ooxml_part_validator.rb +0 -128
- data/lib/uniword/validation/validators/relationship_validator.rb +0 -147
- data/lib/uniword/validation/validators/zip_integrity_validator.rb +0 -110
- data/lib/uniword/validators/element_validator.rb +0 -93
- data/lib/uniword/validators/paragraph_validator.rb +0 -116
- data/lib/uniword/validators/table_validator.rb +0 -134
- data/lib/uniword/validators.rb +0 -9
- data/lib/uniword/warnings/warning.rb +0 -130
- data/lib/uniword/warnings/warning_collector.rb +0 -234
- data/lib/uniword/warnings/warning_report.rb +0 -159
- data/lib/uniword/warnings.rb +0 -9
|
@@ -9,34 +9,39 @@ module Uniword
|
|
|
9
9
|
#
|
|
10
10
|
# Key behavior:
|
|
11
11
|
# - cast(nil) -> nil (doesn't convert to false like OoxmlBoolean)
|
|
12
|
-
# - cast("1") -> true, cast("0") -> false
|
|
12
|
+
# - cast("1"/"true"/"on") -> true, cast("0"/"false"/"off") -> false
|
|
13
|
+
# - cast of any other value raises
|
|
14
|
+
# Lutaml::Model::Type::InvalidValueError instead of passing
|
|
15
|
+
# through unchanged
|
|
13
16
|
# - to_xml(true) -> "1"
|
|
14
17
|
# - to_xml(false) -> "0" (explicit false in original)
|
|
15
18
|
# - to_xml(nil) -> nil (attribute absent, omit from output)
|
|
16
19
|
#
|
|
17
20
|
# This is the right type for attributes like w:locked, w:semiHidden
|
|
18
|
-
# on lsdException where absent = false = omit, but explicit
|
|
19
|
-
#
|
|
21
|
+
# on lsdException where absent = false = omit, but explicit
|
|
22
|
+
# "0" = render "0".
|
|
23
|
+
# Note: Due to cast(nil) = nil, absent attributes also serialize
|
|
24
|
+
# as omitted.
|
|
20
25
|
class OoxmlBooleanOptional < Lutaml::Model::Type::Boolean
|
|
21
26
|
def self.cast(value, _options = {})
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
value
|
|
31
|
-
end
|
|
27
|
+
return value if Lutaml::Model::Utils.uninitialized?(value)
|
|
28
|
+
return nil if value.nil?
|
|
29
|
+
return true if OoxmlBoolean::TRUE_VALUES.include?(value)
|
|
30
|
+
return false if OoxmlBoolean::FALSE_VALUES.include?(value)
|
|
31
|
+
|
|
32
|
+
raise Lutaml::Model::Type::InvalidValueError.new(
|
|
33
|
+
value, OoxmlBoolean::ON_OFF_VALUES
|
|
34
|
+
)
|
|
32
35
|
end
|
|
33
36
|
|
|
34
37
|
def self.serialize(value)
|
|
35
38
|
return nil if value.nil?
|
|
36
|
-
return "1" if
|
|
37
|
-
return "0" if
|
|
39
|
+
return "1" if OoxmlBoolean::TRUE_VALUES.include?(value)
|
|
40
|
+
return "0" if OoxmlBoolean::FALSE_VALUES.include?(value)
|
|
38
41
|
|
|
39
|
-
|
|
42
|
+
raise Lutaml::Model::Type::InvalidValueError.new(
|
|
43
|
+
value, OoxmlBoolean::ON_OFF_VALUES
|
|
44
|
+
)
|
|
40
45
|
end
|
|
41
46
|
|
|
42
47
|
# Override instance to_xml:
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
|
|
5
|
+
module Uniword
|
|
6
|
+
module Ooxml
|
|
7
|
+
module Types
|
|
8
|
+
# ST_ThemeColor (ECMA-376, wml.xsd): theme color reference
|
|
9
|
+
#
|
|
10
|
+
# Carries the full ST_ThemeColor enumeration so models can declare
|
|
11
|
+
# `values: ThemeColorValue::VALUES` on theme color attributes.
|
|
12
|
+
class ThemeColorValue < Lutaml::Model::Type::String
|
|
13
|
+
# Full ST_ThemeColor enumeration from ECMA-376 (wml.xsd)
|
|
14
|
+
VALUES = %w[
|
|
15
|
+
dark1 light1 dark2 light2 accent1 accent2 accent3 accent4
|
|
16
|
+
accent5 accent6 hyperlink followedHyperlink none background1
|
|
17
|
+
text1 background2 text2
|
|
18
|
+
].freeze
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "lutaml/model"
|
|
4
|
+
|
|
5
|
+
module Uniword
|
|
6
|
+
module Ooxml
|
|
7
|
+
module Types
|
|
8
|
+
# ST_UnsignedDecimalNumber (ECMA-376): non-negative integer
|
|
9
|
+
#
|
|
10
|
+
# Constrained integer type shared by unsigned OOXML measures
|
|
11
|
+
# (ST_TwipsMeasure, ST_PointMeasure, ST_PixelsMeasure). Negative
|
|
12
|
+
# values raise Lutaml::Model::Type::MinBoundError at cast time
|
|
13
|
+
# (attribute assignment and XML parsing).
|
|
14
|
+
class UnsignedDecimalNumber < Lutaml::Model::Type::Integer
|
|
15
|
+
# Cast a value to a non-negative Integer
|
|
16
|
+
#
|
|
17
|
+
# @param value [Object] the raw value
|
|
18
|
+
# @param options [Hash] cast options (unused)
|
|
19
|
+
# @return [Integer, nil] the non-negative integer value
|
|
20
|
+
# @raise [Lutaml::Model::Type::MinBoundError] when negative
|
|
21
|
+
def self.cast(value, options = {})
|
|
22
|
+
casted = super
|
|
23
|
+
return casted unless casted.is_a?(::Integer) && casted.negative?
|
|
24
|
+
|
|
25
|
+
raise Lutaml::Model::Type::MinBoundError.new(casted, 0)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
data/lib/uniword/ooxml/types.rb
CHANGED
|
@@ -40,6 +40,16 @@ module Uniword
|
|
|
40
40
|
# Serializes true -> "1", false/nil -> omitted
|
|
41
41
|
autoload :OoxmlBooleanOptional, "#{__dir__}/types/ooxml_boolean_optional"
|
|
42
42
|
|
|
43
|
+
# ST_HexColor constrained string type ("auto" or 6 hex digits)
|
|
44
|
+
autoload :HexColorValue, "#{__dir__}/types/hex_color_value"
|
|
45
|
+
|
|
46
|
+
# ST_ThemeColor enumeration carrier type
|
|
47
|
+
autoload :ThemeColorValue, "#{__dir__}/types/theme_color_value"
|
|
48
|
+
|
|
49
|
+
# ST_UnsignedDecimalNumber constrained integer type (non-negative)
|
|
50
|
+
autoload :UnsignedDecimalNumber,
|
|
51
|
+
"#{__dir__}/types/unsigned_decimal_number"
|
|
52
|
+
|
|
43
53
|
# Relationships namespace type for r:embed/r:link cross-namespace attrs
|
|
44
54
|
autoload :RelationshipId, "#{__dir__}/types/relationship_id"
|
|
45
55
|
|
data/lib/uniword/ooxml.rb
CHANGED
|
@@ -29,6 +29,8 @@ module Uniword
|
|
|
29
29
|
autoload :Types, "#{__dir__}/ooxml/types"
|
|
30
30
|
autoload :PackageFile, "#{__dir__}/ooxml/package_file"
|
|
31
31
|
autoload :ContentTypes, "#{__dir__}/content_types"
|
|
32
|
+
autoload :PartDefinition, "#{__dir__}/ooxml/part_definition"
|
|
33
|
+
autoload :PartRegistry, "#{__dir__}/ooxml/part_registry"
|
|
32
34
|
|
|
33
35
|
# OOXML namespaces - autoload for runtime access
|
|
34
36
|
autoload :Namespaces, "#{__dir__}/ooxml/namespaces"
|
|
@@ -6,14 +6,19 @@ module Uniword
|
|
|
6
6
|
module Properties
|
|
7
7
|
# Namespaced custom type for alignment value
|
|
8
8
|
class AlignmentValue < Lutaml::Model::Type::String
|
|
9
|
+
# Full ST_Jc enumeration from ECMA-376 (wml.xsd)
|
|
10
|
+
VALUES = %w[
|
|
11
|
+
start center end both mediumKashida distribute numTab
|
|
12
|
+
highKashida lowKashida thaiDistribute left right
|
|
13
|
+
].freeze
|
|
9
14
|
end
|
|
10
15
|
|
|
11
16
|
# Paragraph alignment element
|
|
12
17
|
#
|
|
13
|
-
# Represents <w:jc w:val="..."/> where value is
|
|
14
|
-
# - left, center, right, both (justified), distribute
|
|
18
|
+
# Represents <w:jc w:val="..."/> where value is from ST_Jc
|
|
19
|
+
# (ECMA-376), e.g. left, center, right, both (justified), distribute
|
|
15
20
|
class Alignment < Lutaml::Model::Serializable
|
|
16
|
-
attribute :value, AlignmentValue
|
|
21
|
+
attribute :value, AlignmentValue, values: AlignmentValue::VALUES
|
|
17
22
|
|
|
18
23
|
xml do
|
|
19
24
|
element "jc"
|
|
@@ -8,31 +8,77 @@ module Uniword
|
|
|
8
8
|
#
|
|
9
9
|
# Represents border line styles from OOXML specification
|
|
10
10
|
class BorderStyleValue < Lutaml::Model::Type::String
|
|
11
|
+
# Full ST_Border enumeration from ECMA-376 (wml.xsd)
|
|
12
|
+
VALUES = %w[nil none single thick double dotted dashed dotDash dotDotDash
|
|
13
|
+
triple thinThickSmallGap thickThinSmallGap
|
|
14
|
+
thinThickThinSmallGap thinThickMediumGap thickThinMediumGap
|
|
15
|
+
thinThickThinMediumGap thinThickLargeGap thickThinLargeGap
|
|
16
|
+
thinThickThinLargeGap wave doubleWave dashSmallGap
|
|
17
|
+
dashDotStroked threeDEmboss threeDEngrave outset inset apples
|
|
18
|
+
archedScallops babyPacifier babyRattle balloons3Colors
|
|
19
|
+
balloonsHotAir basicBlackDashes basicBlackDots
|
|
20
|
+
basicBlackSquares basicThinLines basicWhiteDashes
|
|
21
|
+
basicWhiteDots basicWhiteSquares basicWideInline
|
|
22
|
+
basicWideMidline basicWideOutline bats birds birdsFlight
|
|
23
|
+
cabins cakeSlice candyCorn celticKnotwork certificateBanner
|
|
24
|
+
chainLink champagneBottle checkedBarBlack checkedBarColor
|
|
25
|
+
checkered christmasTree circlesLines circlesRectangles
|
|
26
|
+
classicalWave clocks compass confetti confettiGrays
|
|
27
|
+
confettiOutline confettiStreamers confettiWhite
|
|
28
|
+
cornerTriangles couponCutoutDashes couponCutoutDots crazyMaze
|
|
29
|
+
creaturesButterfly creaturesFish creaturesInsects
|
|
30
|
+
creaturesLadyBug crossStitch cup decoArch decoArchColor
|
|
31
|
+
decoBlocks diamondsGray doubleD doubleDiamonds earth1 earth2
|
|
32
|
+
earth3 eclipsingSquares1 eclipsingSquares2 eggsBlack fans
|
|
33
|
+
film firecrackers flowersBlockPrint flowersDaisies
|
|
34
|
+
flowersModern1 flowersModern2 flowersPansy flowersRedRose
|
|
35
|
+
flowersRoses flowersTeacup flowersTiny gems gingerbreadMan
|
|
36
|
+
gradient handmade1 handmade2 heartBalloon heartGray hearts
|
|
37
|
+
heebieJeebies holly houseFunky hypnotic iceCreamCones
|
|
38
|
+
lightBulb lightning1 lightning2 mapPins mapleLeaf
|
|
39
|
+
mapleMuffins marquee marqueeToothed moons mosaic musicNotes
|
|
40
|
+
northwest ovals packages palmsBlack palmsColor paperClips
|
|
41
|
+
papyrus partyFavor partyGlass pencils people peopleWaving
|
|
42
|
+
peopleHats poinsettias postageStamp pumpkin1 pushPinNote2
|
|
43
|
+
pushPinNote1 pyramids pyramidsAbove quadrants rings safari
|
|
44
|
+
sawtooth sawtoothGray scaredCat seattle shadowedSquares
|
|
45
|
+
sharksTeeth shorebirdTracks skyrocket snowflakeFancy
|
|
46
|
+
snowflakes sombrero southwest stars starsTop stars3d
|
|
47
|
+
starsBlack starsShadowed sun swirligig tornPaper
|
|
48
|
+
tornPaperBlack trees triangleParty triangles triangle1
|
|
49
|
+
triangle2 triangleCircle1 triangleCircle2 shapes1 shapes2
|
|
50
|
+
twistedLines1 twistedLines2 vine waveline weavingAngles
|
|
51
|
+
weavingBraid weavingRibbon weavingStrips whiteFlowers
|
|
52
|
+
woodwork xIllusions zanyTriangles zigZag zigZagStitch
|
|
53
|
+
custom].freeze
|
|
11
54
|
end
|
|
12
55
|
|
|
13
56
|
# Individual border definition
|
|
14
57
|
#
|
|
15
58
|
# Represents a single border (top, bottom, left, right) with style,
|
|
16
59
|
# size, spacing, and color attributes.
|
|
60
|
+
# style is ST_Border, color is ST_HexColor, themeColor is
|
|
61
|
+
# ST_ThemeColor (ECMA-376).
|
|
17
62
|
#
|
|
18
63
|
# @example Creating a border
|
|
19
64
|
# border = Border.new(
|
|
20
|
-
# style:
|
|
65
|
+
# style: "single",
|
|
21
66
|
# size: 4,
|
|
22
67
|
# space: 1,
|
|
23
|
-
# color:
|
|
68
|
+
# color: "auto"
|
|
24
69
|
# )
|
|
25
70
|
class Border < Lutaml::Model::Serializable
|
|
26
71
|
# Pattern 0: ATTRIBUTES FIRST
|
|
27
|
-
attribute :style, BorderStyleValue
|
|
72
|
+
attribute :style, BorderStyleValue, values: BorderStyleValue::VALUES
|
|
28
73
|
attribute :size, :integer # Size in eighths of a point (1-96)
|
|
29
74
|
attribute :space, :integer # Spacing offset in points (0-31)
|
|
30
|
-
attribute :color,
|
|
31
|
-
attribute :theme_color,
|
|
75
|
+
attribute :color, Ooxml::Types::HexColorValue
|
|
76
|
+
attribute :theme_color, Ooxml::Types::ThemeColorValue,
|
|
77
|
+
values: Ooxml::Types::ThemeColorValue::VALUES
|
|
32
78
|
attribute :theme_shade, :string
|
|
33
79
|
|
|
34
80
|
xml do
|
|
35
|
-
# Use
|
|
81
|
+
# Use "border" as element name for standalone parsing
|
|
36
82
|
element "border"
|
|
37
83
|
namespace Ooxml::Namespaces::WordProcessingML
|
|
38
84
|
|
|
@@ -8,6 +8,8 @@ module Uniword
|
|
|
8
8
|
#
|
|
9
9
|
# Represents vertical alignment types from OOXML specification
|
|
10
10
|
class CellVerticalAlignValue < Lutaml::Model::Type::String
|
|
11
|
+
# Full ST_VerticalJc enumeration from ECMA-376 (wml.xsd)
|
|
12
|
+
VALUES = %w[top center both bottom].freeze
|
|
11
13
|
end
|
|
12
14
|
|
|
13
15
|
# Table cell vertical alignment
|
|
@@ -19,7 +21,8 @@ module Uniword
|
|
|
19
21
|
# valign = CellVerticalAlign.new(value: 'center')
|
|
20
22
|
class CellVerticalAlign < Lutaml::Model::Serializable
|
|
21
23
|
# Pattern 0: ATTRIBUTES FIRST
|
|
22
|
-
attribute :value, CellVerticalAlignValue
|
|
24
|
+
attribute :value, CellVerticalAlignValue,
|
|
25
|
+
values: CellVerticalAlignValue::VALUES
|
|
23
26
|
|
|
24
27
|
xml do
|
|
25
28
|
element "vAlign"
|
|
@@ -5,18 +5,23 @@ require "lutaml/model"
|
|
|
5
5
|
module Uniword
|
|
6
6
|
module Properties
|
|
7
7
|
# Namespaced custom type for color value
|
|
8
|
-
|
|
8
|
+
#
|
|
9
|
+
# Inherits the ST_HexColor constraint ("auto" or six hex digits)
|
|
10
|
+
# from Ooxml::Types::HexColorValue.
|
|
11
|
+
class ColorValueType < Ooxml::Types::HexColorValue
|
|
9
12
|
end
|
|
10
13
|
|
|
11
14
|
# Color value element
|
|
12
15
|
#
|
|
13
16
|
# Represents <w:color w:val="..." w:themeColor="..." w:themeShade="..."/>
|
|
14
|
-
# where value is RGB hex (e.g., "FF0000") and themeColor references
|
|
17
|
+
# where value is RGB hex (e.g., "FF0000") and themeColor references
|
|
18
|
+
# theme (e.g., "background1")
|
|
15
19
|
# themeShade is a hex tint value (e.g., "BF")
|
|
16
20
|
class ColorValue < Lutaml::Model::Serializable
|
|
17
21
|
# Pattern 0: ATTRIBUTES FIRST
|
|
18
22
|
attribute :value, ColorValueType
|
|
19
|
-
attribute :theme_color,
|
|
23
|
+
attribute :theme_color, Ooxml::Types::ThemeColorValue,
|
|
24
|
+
values: Ooxml::Types::ThemeColorValue::VALUES
|
|
20
25
|
attribute :theme_shade, :string
|
|
21
26
|
attribute :theme_tint, :string
|
|
22
27
|
|
|
@@ -6,16 +6,20 @@ module Uniword
|
|
|
6
6
|
module Properties
|
|
7
7
|
# Namespaced custom type for highlight value
|
|
8
8
|
class HighlightValue < Lutaml::Model::Type::String
|
|
9
|
+
# Full ST_HighlightColor enumeration from ECMA-376 (wml.xsd)
|
|
10
|
+
VALUES = %w[
|
|
11
|
+
black blue cyan green magenta red yellow white darkBlue
|
|
12
|
+
darkCyan darkGreen darkMagenta darkRed darkYellow darkGray
|
|
13
|
+
lightGray none
|
|
14
|
+
].freeze
|
|
9
15
|
end
|
|
10
16
|
|
|
11
17
|
# Text highlight element
|
|
12
18
|
#
|
|
13
|
-
# Represents <w:highlight w:val="..."/> where value is
|
|
14
|
-
# -
|
|
15
|
-
# darkGreen, darkMagenta, darkRed, darkYellow, darkGray,
|
|
16
|
-
# lightGray, black, white, none
|
|
19
|
+
# Represents <w:highlight w:val="..."/> where value is from
|
|
20
|
+
# ST_HighlightColor (ECMA-376)
|
|
17
21
|
class Highlight < Lutaml::Model::Serializable
|
|
18
|
-
attribute :value, HighlightValue
|
|
22
|
+
attribute :value, HighlightValue, values: HighlightValue::VALUES
|
|
19
23
|
|
|
20
24
|
xml do
|
|
21
25
|
element "highlight"
|
|
@@ -23,9 +23,10 @@ module Uniword
|
|
|
23
23
|
class Shading < Lutaml::Model::Serializable
|
|
24
24
|
# Pattern 0: ATTRIBUTES FIRST
|
|
25
25
|
attribute :pattern, ShadingPatternValue
|
|
26
|
-
attribute :color,
|
|
27
|
-
attribute :fill,
|
|
28
|
-
attribute :theme_fill,
|
|
26
|
+
attribute :color, Ooxml::Types::HexColorValue
|
|
27
|
+
attribute :fill, Ooxml::Types::HexColorValue
|
|
28
|
+
attribute :theme_fill, Ooxml::Types::ThemeColorValue,
|
|
29
|
+
values: Ooxml::Types::ThemeColorValue::VALUES
|
|
29
30
|
|
|
30
31
|
xml do
|
|
31
32
|
element "shd"
|
|
@@ -8,6 +8,10 @@ module Uniword
|
|
|
8
8
|
#
|
|
9
9
|
# Represents alignment types for tab stops
|
|
10
10
|
class TabAlignmentValue < Lutaml::Model::Type::String
|
|
11
|
+
# Full ST_TabJc enumeration from ECMA-376 (wml.xsd)
|
|
12
|
+
VALUES = %w[
|
|
13
|
+
clear start center end decimal bar num left right
|
|
14
|
+
].freeze
|
|
11
15
|
end
|
|
12
16
|
|
|
13
17
|
# Tab leader enumeration
|
|
@@ -28,7 +32,8 @@ module Uniword
|
|
|
28
32
|
# )
|
|
29
33
|
class TabStop < Lutaml::Model::Serializable
|
|
30
34
|
# Pattern 0: ATTRIBUTES FIRST
|
|
31
|
-
attribute :alignment, TabAlignmentValue
|
|
35
|
+
attribute :alignment, TabAlignmentValue,
|
|
36
|
+
values: TabAlignmentValue::VALUES
|
|
32
37
|
attribute :position, :integer # Position in twips
|
|
33
38
|
attribute :leader, TabLeaderValue
|
|
34
39
|
|
|
@@ -9,7 +9,10 @@ module Uniword
|
|
|
9
9
|
# Represents <w:jc> element with val attribute for table alignment.
|
|
10
10
|
# Used in table properties (w:tblPr) for table positioning.
|
|
11
11
|
class TableJustification < Lutaml::Model::Serializable
|
|
12
|
-
|
|
12
|
+
# Full ST_JcTable enumeration from ECMA-376 (wml.xsd)
|
|
13
|
+
VALUES = %w[center end left right start].freeze
|
|
14
|
+
|
|
15
|
+
attribute :value, :string, values: VALUES
|
|
13
16
|
|
|
14
17
|
xml do
|
|
15
18
|
element "jc"
|
|
@@ -12,10 +12,12 @@ module Uniword
|
|
|
12
12
|
#
|
|
13
13
|
# Represents <w:u w:val="..."/> where value is:
|
|
14
14
|
# - single, double, thick, dotted, dashed, wave, none, etc.
|
|
15
|
+
# color is ST_HexColor, themeColor is ST_ThemeColor (ECMA-376)
|
|
15
16
|
class Underline < Lutaml::Model::Serializable
|
|
16
17
|
attribute :value, UnderlineValue
|
|
17
|
-
attribute :color,
|
|
18
|
-
attribute :theme_color,
|
|
18
|
+
attribute :color, Ooxml::Types::HexColorValue
|
|
19
|
+
attribute :theme_color, Ooxml::Types::ThemeColorValue,
|
|
20
|
+
values: Ooxml::Types::ThemeColorValue::VALUES
|
|
19
21
|
attribute :theme_shade, :string
|
|
20
22
|
|
|
21
23
|
xml do
|
|
@@ -6,14 +6,17 @@ module Uniword
|
|
|
6
6
|
module Properties
|
|
7
7
|
# Namespaced custom type for vertical alignment value
|
|
8
8
|
class VerticalAlignValue < Lutaml::Model::Type::String
|
|
9
|
+
# Full ST_VerticalAlignRun enumeration from ECMA-376 (wml.xsd)
|
|
10
|
+
VALUES = %w[baseline superscript subscript].freeze
|
|
9
11
|
end
|
|
10
12
|
|
|
11
13
|
# Text vertical alignment element
|
|
12
14
|
#
|
|
13
|
-
# Represents <w:vertAlign w:val="..."/> where value is
|
|
14
|
-
# - baseline, superscript, subscript
|
|
15
|
+
# Represents <w:vertAlign w:val="..."/> where value is from
|
|
16
|
+
# ST_VerticalAlignRun (ECMA-376): baseline, superscript, subscript
|
|
15
17
|
class VerticalAlign < Lutaml::Model::Serializable
|
|
16
|
-
attribute :value, VerticalAlignValue
|
|
18
|
+
attribute :value, VerticalAlignValue,
|
|
19
|
+
values: VerticalAlignValue::VALUES
|
|
17
20
|
|
|
18
21
|
xml do
|
|
19
22
|
element "vertAlign"
|
|
@@ -40,6 +40,10 @@ module Uniword
|
|
|
40
40
|
|
|
41
41
|
# Add a new comment to the document.
|
|
42
42
|
#
|
|
43
|
+
# The comment is registered in the document's CommentsPart, which
|
|
44
|
+
# the save path serializes to word/comments.xml. The collection
|
|
45
|
+
# assigns a sequential decimal ID (OOXML ST_DecimalNumber).
|
|
46
|
+
#
|
|
43
47
|
# @param text [String] Comment text
|
|
44
48
|
# @param author [String] Author name
|
|
45
49
|
# @param initials [String, nil] Author initials
|
|
@@ -50,6 +54,7 @@ module Uniword
|
|
|
50
54
|
author: author,
|
|
51
55
|
initials: initials,
|
|
52
56
|
)
|
|
57
|
+
comment.comment_id = nil
|
|
53
58
|
comments_part.add_comment(comment)
|
|
54
59
|
end
|
|
55
60
|
|
|
@@ -74,6 +79,7 @@ module Uniword
|
|
|
74
79
|
text: text,
|
|
75
80
|
author: author,
|
|
76
81
|
)
|
|
82
|
+
comment.comment_id = nil
|
|
77
83
|
comments_part.add_comment(comment)
|
|
78
84
|
end
|
|
79
85
|
|
|
@@ -216,15 +222,23 @@ module Uniword
|
|
|
216
222
|
#
|
|
217
223
|
# @return [Uniword::CommentsPart] The comments collection
|
|
218
224
|
def comments_part
|
|
219
|
-
@comments_part ||=
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
225
|
+
@comments_part ||= migrate_comments(document.comments)
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
# Migrate legacy Array storage into a CommentsPart, preserving
|
|
229
|
+
# its entries; initialize the collection when absent.
|
|
230
|
+
#
|
|
231
|
+
# @param existing [CommentsPart, Array, nil] current value
|
|
232
|
+
# @return [Uniword::CommentsPart] The comments collection
|
|
233
|
+
def migrate_comments(existing)
|
|
234
|
+
case existing
|
|
235
|
+
when CommentsPart then existing
|
|
236
|
+
when Array
|
|
237
|
+
part = CommentsPart.new
|
|
238
|
+
existing.each { |c| part.add_comment(c) }
|
|
239
|
+
document.comments = part
|
|
240
|
+
else
|
|
241
|
+
document.comments = CommentsPart.new
|
|
228
242
|
end
|
|
229
243
|
end
|
|
230
244
|
|
data/lib/uniword/revision.rb
CHANGED
|
@@ -34,6 +34,15 @@ module Uniword
|
|
|
34
34
|
#
|
|
35
35
|
# @see TrackedChanges For revision collection management
|
|
36
36
|
class Revision < Lutaml::Model::Serializable
|
|
37
|
+
# Unique revision identifier
|
|
38
|
+
attribute :revision_id, :string
|
|
39
|
+
|
|
40
|
+
# Author name
|
|
41
|
+
attribute :author, :string
|
|
42
|
+
|
|
43
|
+
# Revision date/time
|
|
44
|
+
attribute :date, :string
|
|
45
|
+
|
|
37
46
|
# OOXML namespace configuration
|
|
38
47
|
xml do
|
|
39
48
|
element "ins"
|
|
@@ -44,15 +53,6 @@ module Uniword
|
|
|
44
53
|
map_attribute "date", to: :date
|
|
45
54
|
end
|
|
46
55
|
|
|
47
|
-
# Unique revision identifier
|
|
48
|
-
attribute :revision_id, :string
|
|
49
|
-
|
|
50
|
-
# Author name
|
|
51
|
-
attribute :author, :string
|
|
52
|
-
|
|
53
|
-
# Revision date/time
|
|
54
|
-
attribute :date, :string
|
|
55
|
-
|
|
56
56
|
# Revision type (:insert, :delete, :format_change)
|
|
57
57
|
attr_accessor :type
|
|
58
58
|
|
|
@@ -62,8 +62,6 @@ module Uniword
|
|
|
62
62
|
file_path
|
|
63
63
|
end
|
|
64
64
|
|
|
65
|
-
private
|
|
66
|
-
|
|
67
65
|
# Generate complete class code
|
|
68
66
|
#
|
|
69
67
|
# @param element_name [String] XML element name
|
|
@@ -97,6 +95,8 @@ module Uniword
|
|
|
97
95
|
RUBY
|
|
98
96
|
end
|
|
99
97
|
|
|
98
|
+
private
|
|
99
|
+
|
|
100
100
|
# Generate attribute declarations
|
|
101
101
|
# CRITICAL: These MUST come BEFORE xml mapping (Pattern 0)
|
|
102
102
|
#
|
|
@@ -105,21 +105,37 @@ module Uniword
|
|
|
105
105
|
def generate_attributes(attributes)
|
|
106
106
|
return "" if attributes.empty?
|
|
107
107
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
108
|
+
attributes.map { |attr| generate_attribute(attr) }.join("\n")
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Generate one attribute declaration
|
|
112
|
+
#
|
|
113
|
+
# @param attr [Hash] Attribute definition
|
|
114
|
+
# @return [String] Attribute declaration code
|
|
115
|
+
def generate_attribute(attr)
|
|
116
|
+
attr_code = " attribute :#{attr['name']}, " \
|
|
117
|
+
"#{attribute_type(attr['type'])}"
|
|
118
|
+
attr_code += ", collection: true" if attr["collection"]
|
|
119
|
+
attr_code += ", initialize_empty: true" if attr["collection"]
|
|
120
|
+
if attr["values"]
|
|
121
|
+
attr_code += ", values: %w[#{attr['values'].join(' ')}]"
|
|
120
122
|
end
|
|
123
|
+
attr_code += ", pattern: /#{attr['pattern']}/" if attr["pattern"]
|
|
124
|
+
attr_code
|
|
125
|
+
end
|
|
121
126
|
|
|
122
|
-
|
|
127
|
+
# Normalize an attribute type from YAML to Ruby code
|
|
128
|
+
# Primitive types become symbols (":string"), custom type class
|
|
129
|
+
# names are passed through verbatim
|
|
130
|
+
#
|
|
131
|
+
# @param type [String, Symbol] Type from YAML attribute definition
|
|
132
|
+
# @return [String] Ruby type expression
|
|
133
|
+
def attribute_type(type)
|
|
134
|
+
type = type.to_s
|
|
135
|
+
return ":#{type.downcase}" if %w[String Integer].include?(type)
|
|
136
|
+
return type if type.start_with?(":") || type.include?("::")
|
|
137
|
+
|
|
138
|
+
":#{type}"
|
|
123
139
|
end
|
|
124
140
|
|
|
125
141
|
# Generate XML mapping block
|
|
@@ -8,8 +8,11 @@ module Uniword
|
|
|
8
8
|
#
|
|
9
9
|
# Generated from OOXML schema: shared_types.yml
|
|
10
10
|
# Element: <st:hex_color>
|
|
11
|
+
#
|
|
12
|
+
# Value constrained to ST_HexColor (ECMA-376): "auto" or six
|
|
13
|
+
# hexadecimal digits; see Ooxml::Types::HexColorValue.
|
|
11
14
|
class HexColor < Lutaml::Model::Serializable
|
|
12
|
-
attribute :val,
|
|
15
|
+
attribute :val, Uniword::Ooxml::Types::HexColorValue
|
|
13
16
|
|
|
14
17
|
xml do
|
|
15
18
|
element "hex_color"
|
|
@@ -8,8 +8,11 @@ module Uniword
|
|
|
8
8
|
#
|
|
9
9
|
# Generated from OOXML schema: shared_types.yml
|
|
10
10
|
# Element: <st:pixel_measure>
|
|
11
|
+
#
|
|
12
|
+
# Value constrained to ST_PixelsMeasure (ECMA-376): non-negative
|
|
13
|
+
# integer; see Ooxml::Types::UnsignedDecimalNumber.
|
|
11
14
|
class PixelMeasure < Lutaml::Model::Serializable
|
|
12
|
-
attribute :val,
|
|
15
|
+
attribute :val, Uniword::Ooxml::Types::UnsignedDecimalNumber
|
|
13
16
|
|
|
14
17
|
xml do
|
|
15
18
|
element "pixel_measure"
|
|
@@ -8,8 +8,11 @@ module Uniword
|
|
|
8
8
|
#
|
|
9
9
|
# Generated from OOXML schema: shared_types.yml
|
|
10
10
|
# Element: <st:point_measure>
|
|
11
|
+
#
|
|
12
|
+
# Value constrained to ST_PointMeasure (ECMA-376): non-negative
|
|
13
|
+
# integer; see Ooxml::Types::UnsignedDecimalNumber.
|
|
11
14
|
class PointMeasure < Lutaml::Model::Serializable
|
|
12
|
-
attribute :val,
|
|
15
|
+
attribute :val, Uniword::Ooxml::Types::UnsignedDecimalNumber
|
|
13
16
|
|
|
14
17
|
xml do
|
|
15
18
|
element "point_measure"
|
|
@@ -8,8 +8,13 @@ module Uniword
|
|
|
8
8
|
#
|
|
9
9
|
# Generated from OOXML schema: shared_types.yml
|
|
10
10
|
# Element: <st:text_alignment>
|
|
11
|
+
#
|
|
12
|
+
# Value constrained to ST_TextAlignment (ECMA-376, wml.xsd).
|
|
11
13
|
class TextAlignment < Lutaml::Model::Serializable
|
|
12
|
-
|
|
14
|
+
# Full ST_TextAlignment enumeration from ECMA-376 (wml.xsd)
|
|
15
|
+
VALUES = %w[top center baseline bottom auto].freeze
|
|
16
|
+
|
|
17
|
+
attribute :val, :string, values: VALUES
|
|
13
18
|
|
|
14
19
|
xml do
|
|
15
20
|
element "text_alignment"
|
|
@@ -8,8 +8,11 @@ module Uniword
|
|
|
8
8
|
#
|
|
9
9
|
# Generated from OOXML schema: shared_types.yml
|
|
10
10
|
# Element: <st:twips_measure>
|
|
11
|
+
#
|
|
12
|
+
# Value constrained to ST_TwipsMeasure (ECMA-376): non-negative
|
|
13
|
+
# integer; see Ooxml::Types::UnsignedDecimalNumber.
|
|
11
14
|
class TwipsMeasure < Lutaml::Model::Serializable
|
|
12
|
-
attribute :val,
|
|
15
|
+
attribute :val, Uniword::Ooxml::Types::UnsignedDecimalNumber
|
|
13
16
|
|
|
14
17
|
xml do
|
|
15
18
|
element "twips_measure"
|
|
@@ -26,7 +26,7 @@ module Uniword
|
|
|
26
26
|
map_attribute "panose", to: :panose, render_nil: false
|
|
27
27
|
map_attribute "pitchFamily", to: :pitch_family, render_nil: false
|
|
28
28
|
map_attribute "charset", to: :charset, render_nil: false
|
|
29
|
-
map_attribute "altText", to: :
|
|
29
|
+
map_attribute "altText", to: :alt_text, render_nil: false
|
|
30
30
|
map_attribute "combinationId", to: :combination_id, render_nil: false
|
|
31
31
|
map_attribute "growingEditing", to: :growing_editing, render_nil: false
|
|
32
32
|
end
|