porrima 0.2.1 → 0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 980ed5bd98192197baedd3aed4c98742c82e805b86fee9398f46ca2c1de5dfb0
4
- data.tar.gz: 5f788bae42d8cd6420d4663ca52490a7e59a2ad8a06ec02d34539d69baee321d
3
+ metadata.gz: 9cb36f8d5f52c2bd1c4ec9b43223de3fea75b17b4059402ce5659fc14bc5fe9e
4
+ data.tar.gz: 68e095935908555e20d8f76f4a4eaa559a7ebd909be5c72d074e6bce9ab84f45
5
5
  SHA512:
6
- metadata.gz: cc589b70eb6b4129da8e0663206d283b586bf54cabd33d6667d2ad0a171e50c69ce2388c35d8b32929ebce1de03fa6e72149daeb049a04261bbd3a79544affd4
7
- data.tar.gz: 2c6a2a978997338aa81b25911c48d1b3fb58e086e0a2511149b9d6659fb00083d00792eb2c567735c5636d70f6b14202e588b6d8ab423b169fe82d187a619504
6
+ metadata.gz: 8ec0cc6a0a47b1cd2570d33377fee475a3c45e3f787d67e598ef19bedace1a99624fc4ad1e7771f7fe338c6fa6a82092db7d76304155d4069209f9a344b387f2
7
+ data.tar.gz: e7a8308c5d1829640d1db2fb6fee7497140201968cc7e0ebcab5e066bd657ce1f512e5fa9d76bfdf059919d8142879665fad76d1407b8d47d4d5ddd4af7fa212
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.0 — 2026-09-24
4
+
5
+ - Add sparse cell and ordered slide difference APIs without application dependencies.
6
+
3
7
  ## 0.2.1 — 2026-09-21
4
8
 
5
9
  - Add a deterministic side-by-side diff demo image and regeneration task.
data/README.md CHANGED
@@ -34,6 +34,7 @@ color, width, truncation, caching, and other display policy to the caller.
34
34
  - Context hunks, change statistics, gutter marks, and paired rows
35
35
  - Unified diff output with strict patch parsing, application, and reversal
36
36
  - Three-way merge with structured conflicts, output regions, and immutable resolution
37
+ - Sparse sheet cell changes and ordered slide changes without application dependencies
37
38
  - CLI output as unified text or JSON
38
39
  - No runtime dependencies
39
40
 
@@ -73,6 +74,31 @@ puts diff.to_unified(old_name: "a/example", new_name: "b/example")
73
74
  | `Porrima::Inline.refine(before, after)` | Word- or character-level spans |
74
75
  | `Porrima::Patch.parse(text)` | Parsed unified file diffs |
75
76
  | `Porrima::Merge.three_way(...)` | Structured three-way merge result |
77
+ | `Porrima::Structured.sheet(before, after)` | Changed cells in row/column order |
78
+ | `Porrima::Structured.slides(before, after)` | Added, removed, or modified slide positions |
79
+
80
+ ### Structured data
81
+
82
+ `Structured.sheet` accepts sparse sheets with `row_count`, `column_count`, and
83
+ `each_in(top, left, bottom, right)`, such as `Denebola::Sheet` returned by
84
+ `Rukbat::Workbook#sheet`. It returns only changed cells, with zero-based
85
+ `row` and `column`, `kind`, `before`, and `after`. A missing cell is `nil`.
86
+
87
+ `Structured.slides` accepts two ordered arrays. Pass a block to compare a
88
+ projection of each slide, while the results retain the original slide values:
89
+
90
+ ```ruby
91
+ before = old_deck.slides
92
+ after = new_deck.slides
93
+ changes = Porrima::Structured.slides(before, after) do |slide|
94
+ [slide.layout, slide.slots.transform_values(&:text), slide.notes]
95
+ end
96
+ ```
97
+
98
+ Each change has `kind`, zero-based `old_index`/`new_index`, and `before`/`after`.
99
+ An absent side has a `nil` index and value. Choose a projection that includes
100
+ everything relevant to your comparison; for exact Markdown changes, compare
101
+ the decks' source text with `Porrima.diff`.
76
102
 
77
103
  ### Diff result
78
104
 
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Porrima
4
+ module Structured
5
+ CellChange = Struct.new(:kind, :row, :column, :before, :after, keyword_init: true)
6
+ SlideChange = Struct.new(:kind, :old_index, :new_index, :before, :after, keyword_init: true)
7
+
8
+ module_function
9
+
10
+ # Coordinates are zero-based, matching the sparse sheet's each_in points.
11
+ def sheet(before, after)
12
+ old_cells = cells(before)
13
+ new_cells = cells(after)
14
+ (old_cells.keys | new_cells.keys).sort.filter_map do |row, column|
15
+ position = [row, column]
16
+ old_present = old_cells.key?(position)
17
+ new_present = new_cells.key?(position)
18
+ old_value = old_cells[position]
19
+ new_value = new_cells[position]
20
+ next if old_present && new_present && old_value == new_value
21
+
22
+ kind = old_present ? (new_present ? :modified : :removed) : :added
23
+ CellChange.new(kind: kind, row: row, column: column, before: old_value, after: new_value).freeze
24
+ end.freeze
25
+ end
26
+
27
+ # The block selects the content used to align slides. Without it, values
28
+ # themselves are compared. Positions are zero-based, matching Deck#slide.
29
+ def slides(before, after, &identity)
30
+ identity ||= ->(slide) { slide }
31
+ ids = {}
32
+ old_ids = slide_ids(before, ids, identity)
33
+ new_ids = slide_ids(after, ids, identity)
34
+ Porrima.diff(old_ids, new_ids).rows.filter_map do |row|
35
+ next if row.kind == :equal
36
+
37
+ old_index = row.old_line && row.old_line - 1
38
+ new_index = row.new_line && row.new_line - 1
39
+ SlideChange.new(kind: row.kind, old_index: old_index, new_index: new_index,
40
+ before: old_index && before[old_index], after: new_index && after[new_index]).freeze
41
+ end.freeze
42
+ end
43
+
44
+ def cells(sheet)
45
+ entries = {}
46
+ return entries if sheet.row_count.zero? || sheet.column_count.zero?
47
+
48
+ sheet.each_in(0, 0, sheet.row_count - 1, sheet.column_count - 1) do |point, value|
49
+ entries[[point.row, point.column]] = value
50
+ end
51
+ entries
52
+ end
53
+ private_class_method :cells
54
+
55
+ def slide_ids(slides, ids, identity)
56
+ slides.map { |slide| ids[identity.call(slide)] ||= ids.length.to_s }
57
+ end
58
+ private_class_method :slide_ids
59
+ end
60
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Porrima
4
- VERSION = "0.2.1"
4
+ VERSION = "0.3.0"
5
5
  end
data/lib/porrima.rb CHANGED
@@ -11,6 +11,7 @@ require_relative "porrima/diff"
11
11
  require_relative "porrima/patch"
12
12
  require_relative "porrima/inline"
13
13
  require_relative "porrima/merge"
14
+ require_relative "porrima/structured"
14
15
 
15
16
  module Porrima
16
17
  module_function
data/sig/porrima.rbs CHANGED
@@ -134,6 +134,27 @@ module Porrima
134
134
  def self.conflict_inline: (Conflict) -> { ours: Array[Span], theirs: Array[Span] }
135
135
  end
136
136
 
137
+ module Structured
138
+ class CellChange < Struct[untyped]
139
+ attr_accessor kind: :added | :modified | :removed
140
+ attr_accessor row: Integer
141
+ attr_accessor column: Integer
142
+ attr_accessor before: untyped
143
+ attr_accessor after: untyped
144
+ def self.new: (kind: (:added | :modified | :removed), row: Integer, column: Integer, before: untyped, after: untyped) -> instance
145
+ end
146
+ class SlideChange < Struct[untyped]
147
+ attr_accessor kind: :added | :modified | :removed
148
+ attr_accessor old_index: Integer?
149
+ attr_accessor new_index: Integer?
150
+ attr_accessor before: untyped
151
+ attr_accessor after: untyped
152
+ def self.new: (kind: (:added | :modified | :removed), old_index: Integer?, new_index: Integer?, before: untyped, after: untyped) -> instance
153
+ end
154
+ def self.sheet: (untyped before, untyped after) -> Array[CellChange]
155
+ def self.slides: (Array[untyped] before, Array[untyped] after) ?{ (untyped) -> untyped } -> Array[SlideChange]
156
+ end
157
+
137
158
  def self.diff: (lines, lines, ?context: Integer, ?budget: Budget?) -> Diff
138
159
  def self.edits: (lines, lines, ?budget: Budget?) -> Array[Edit]
139
160
  def self.hunks: (lines, lines, ?context: Integer, ?budget: Budget?) -> Array[Hunk]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: porrima
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yudai Takada
@@ -34,6 +34,7 @@ files:
34
34
  - lib/porrima/merge.rb
35
35
  - lib/porrima/myers.rb
36
36
  - lib/porrima/patch.rb
37
+ - lib/porrima/structured.rb
37
38
  - lib/porrima/unified.rb
38
39
  - lib/porrima/version.rb
39
40
  - sig/porrima.rbs