nokodiff 1.0.0.rc1 → 1.1.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: 98b3f977e0c9f7e35ccff54cbab81944e22bbcd3b7bb29a5a383fbd0a2668186
4
- data.tar.gz: 7dbb7c2c74e1d85d245a48722e91d2ab8f89dde3508e32cfb3fe350ea30fd75b
3
+ metadata.gz: 856dc58d68b66f6af795512bb66066cc50c10a7a11efc6b20b138f656cf50c1b
4
+ data.tar.gz: d7d345134c3e9d588a71873ffbc680b2e4ba67e0d1c9f76ba34a98050ace98cb
5
5
  SHA512:
6
- metadata.gz: 7a8f9d05204c541ceba28f32d5d0f233dacf510d6b03391aab292fca7e649ca302b291543b14a9c27cfdc685d9fb3d250d66ebd9aa60107ffd36413c6b8c1256
7
- data.tar.gz: d43cf00ad191e146e35f9a581d8a69de0076eec5618c94361e899a74cc11e2aba51deeda8bf99d16572b3da42397d79e7cc84704f16220fd22c04e3f0b2eb901
6
+ metadata.gz: ee93167f9ed499b49fccd29048e9544ca0daa306ee7fd7d9bf00ce6a28603ab4a93620148cf31d1ffb3de83cc8ce3ba8f8d2621b00727f182735e5fe8d5a576c
7
+ data.tar.gz: 50e10242d8a451712ad138add211346d278f967a6ea1e0e8e4c4277481c71689462cd1e55891157bf0b91b8d47fc7fa855c9faf11aef6bbaaab798fdf193bf69
@@ -9,30 +9,26 @@ $comparison-sidebar-width: 40px;
9
9
  $comparison-sidebar-padding: 15px;
10
10
  $comparison-sidebar-offset: $comparison-sidebar-width + $comparison-sidebar-padding;
11
11
 
12
- .visually-hidden {
13
- position: absolute !important;
14
- width: 1px !important;
15
- height: 1px !important;
16
- // If margin is set to a negative value it can cause text to be announced in
17
- // the wrong order in VoiceOver for OSX
18
- margin: 0 !important;
19
- padding: 0 !important;
20
- overflow: hidden !important;
21
-
22
- clip: rect(0 0 0 0) !important;
23
- clip-path: inset(50%) !important;
24
-
25
- border: 0 !important;
26
-
27
- // For long content, line feeds are not interpreted as spaces and small width
28
- // causes content to wrap 1 word per line:
29
- // https://medium.com/@jessebeach/beware-smushed-off-screen-accessible-text-5952a4c2cbfe
30
- white-space: nowrap !important;
31
-
32
- // Prevent users from selecting or copying visually-hidden text. This prevents
33
- // a user unintentionally copying more text than they intended and needing to
34
- // manually trim it down again.
35
- user-select: none !important;
12
+ @mixin diff-block {
13
+ position: relative;
14
+ background: $added-color;
15
+ padding-left: $comparison-sidebar-padding;
16
+ margin-left: -$comparison-sidebar-padding;
17
+ width: calc(100% + $comparison-sidebar-padding);
18
+
19
+ &:before {
20
+ content: " ";
21
+ position: absolute;
22
+ left: -$comparison-sidebar-width;
23
+ width: $comparison-sidebar-width;
24
+ height: 100%;
25
+ font-weight: normal;
26
+ min-height: 1.5em;
27
+ line-height: 1.5em;
28
+ text-align: center;
29
+ z-index: 10;
30
+ background: $diff-marker-added-color;
31
+ }
36
32
  }
37
33
 
38
34
  .visually-hidden {
@@ -59,7 +55,6 @@ $comparison-sidebar-offset: $comparison-sidebar-width + $comparison-sidebar-padd
59
55
  // a user unintentionally copying more text than they intended and needing to
60
56
  // manually trim it down again.
61
57
  user-select: none !important;
62
-
63
58
  }
64
59
 
65
60
  .compare-editions {
@@ -95,7 +90,7 @@ $comparison-sidebar-offset: $comparison-sidebar-width + $comparison-sidebar-padd
95
90
  bottom: 0;
96
91
  left: -$comparison-sidebar-padding;
97
92
  min-height: 1.5em;
98
- width: 100vw;
93
+ right: 0;
99
94
  display: block;
100
95
  z-index: -1;
101
96
  }
@@ -148,14 +143,23 @@ $comparison-sidebar-offset: $comparison-sidebar-width + $comparison-sidebar-padd
148
143
  }
149
144
  }
150
145
 
151
- // Global govspeak-specific overrides
146
+ // Govspeak-specific overrides
152
147
  .gem-c-govspeak & {
153
- &::before { min-height: 1.3157894737em; }
148
+ &::before { min-height: 5em; }
149
+ }
150
+
151
+ .diff .gem-c-button.govuk-button{
152
+ margin-top: 22px;
153
+ }
154
+
155
+ .form-download .diff {
156
+ padding-top: 10px;
157
+ padding-bottom: 3px;
154
158
  }
155
159
 
156
160
  // Inset/callout elements overrides
157
161
 
158
- .address {
162
+ .address, .contact {
159
163
  .diff{
160
164
  $address-offset: -16px;
161
165
 
@@ -171,6 +175,38 @@ $comparison-sidebar-offset: $comparison-sidebar-width + $comparison-sidebar-padd
171
175
 
172
176
  .help-notice {
173
177
  $help-notice-offset: -45px;
178
+
179
+ &:before {
180
+ display: none;
181
+ }
182
+
183
+ p {
184
+ position: relative;
185
+
186
+ &:before {
187
+ content: "!";
188
+ font-weight: 700;
189
+ border-radius: 50%;
190
+ color: var(--govuk-body-background-colour, #ffffff);
191
+ background: var(--govuk-text-colour, #0b0c0c);
192
+ font-size: 30px;
193
+ line-height: 29px;
194
+ text-align: center;
195
+ position: absolute;
196
+ margin-top: -5px;
197
+ left: $help-notice-offset;
198
+ min-width: 35px;
199
+ min-height: 35px;
200
+ }
201
+
202
+ &:first-child:after {
203
+ content: ".";
204
+ display: block;
205
+ clear: both;
206
+ visibility: hidden;
207
+ }
208
+ }
209
+
174
210
  .diff {
175
211
  &::after, &::before {
176
212
  top: -15px;
@@ -179,8 +215,6 @@ $comparison-sidebar-offset: $comparison-sidebar-width + $comparison-sidebar-padd
179
215
  }
180
216
 
181
217
  &::before {
182
- top: -15px;
183
- min-height: calc(1.5em + 30px);
184
218
  left: -$comparison-sidebar-offset + $help-notice-offset;
185
219
  }
186
220
  }
@@ -228,6 +262,15 @@ $comparison-sidebar-offset: $comparison-sidebar-width + $comparison-sidebar-padd
228
262
  $govuk-list-offset: -20px;
229
263
 
230
264
  .gem-c-govspeak & {
265
+ ul.list-no-bullets {
266
+ list-style: none;
267
+ padding-left: 0;
268
+
269
+ span.diff:before {
270
+ left: -$comparison-sidebar-width - $comparison-sidebar-padding;
271
+ }
272
+ }
273
+
231
274
  ul li span.diff, ul span.diff {
232
275
  &::after {
233
276
  left: -$comparison-sidebar-padding + $govuk-list-offset;
@@ -241,11 +284,6 @@ $comparison-sidebar-offset: $comparison-sidebar-width + $comparison-sidebar-padd
241
284
  ol li span.diff {
242
285
  list-style-type: decimal;
243
286
 
244
- &::marker {
245
- background-color: #0b0c0c;
246
- border-radius: 50%;
247
- }
248
-
249
287
  &::after {
250
288
  left: $comparison-sidebar-padding;
251
289
  }
@@ -255,53 +293,176 @@ $comparison-sidebar-offset: $comparison-sidebar-width + $comparison-sidebar-padd
255
293
  }
256
294
  }
257
295
 
296
+ ol:not(.steps) span.diff {
297
+ &::before {
298
+ left: -75px;
299
+ }
300
+
301
+ &::after {
302
+ left: -75px;
303
+ }
304
+ }
305
+
306
+ // Deal with the number values of ordered lists (including steps)
307
+ // by changing the increment value depending on sequence of diffs
308
+ ol {
309
+ counter-reset: item 0;
310
+ list-style: none;
311
+ margin-left: 20px;
312
+
313
+ li {
314
+ position: relative;
315
+ }
316
+
317
+ li:before {
318
+ position: absolute;
319
+ left: -20px;
320
+ counter-increment: item 1;
321
+ content: counter(item);
322
+ }
323
+
324
+ // Over-ride style for <li> elements inside a span.diff
325
+ // Ideally the markup would be changed so this is not needed
326
+ &.steps > span.diff > li:before {
327
+ left: 0;
328
+ }
329
+
330
+ li:has(.diff) + li:not(:has(.diff)),
331
+ li:not(:has(.diff)) + li:has(.diff),
332
+ li:not(:has(.diff)) + li:not(:has(.diff)) {
333
+ &:before {
334
+ counter-increment: item 1;
335
+ content: counter(item);
336
+ };
337
+ }
338
+
339
+ li:has(.del) + li:has(.ins) {
340
+ &:before {
341
+ counter-increment: item 0;
342
+ content: counter(item);
343
+ }
344
+ }
345
+
346
+ // This is required to over-ride the visually-hidden element
347
+ // that is otherwise assigned the first counter
348
+ // when a new set of steps are added
349
+ & > span.steps > span + li:before {
350
+ content: "1";
351
+ }
352
+ }
353
+
258
354
  //govuk "steps"-style ol overrides
259
355
  $steps-list-offset: -48px;
260
356
 
261
357
  ol.steps {
262
- li{
263
- display: list-item;
264
- list-style-type: decimal;
265
- padding-left: 0.25em;
266
- margin-left: 2.25em;
358
+ @extend .steps;
359
+
360
+ &:has(>span.diff.del) {
361
+ @include diff-block;
362
+
363
+ background: $removed-color;
364
+ }
365
+
366
+ &:has(>span.diff.ins) {
367
+ @include diff-block;
368
+
369
+ background: $added-color;
370
+ }
371
+
372
+ margin-left: -$comparison-sidebar-padding;
373
+ width: calc(100% + $comparison-sidebar-padding);
374
+
375
+ li {
376
+ position: relative;
377
+ margin-top: 0.75em;
378
+ margin-bottom: 0.75em;
379
+ padding-top: 0;
380
+ padding-bottom: 0;
381
+
382
+ & > p {
383
+ margin-left: $comparison-sidebar-padding;
384
+ }
385
+
386
+ &:has(.del) {
387
+ background: $removed-color;
388
+ }
389
+
390
+ &:has(.ins) {
391
+ background: $added-color;
392
+ }
267
393
 
268
394
  &::before {
269
- display: none;
395
+ top: 0;
396
+ margin-left: $comparison-sidebar-padding;
397
+ }
398
+
399
+ & > span {
400
+ margin-left: $comparison-sidebar-padding;
401
+
402
+ p {
403
+ margin-bottom: 0;
404
+ }
270
405
  }
271
- &::after { left: -$comparison-sidebar-padding + $steps-list-offset !important; }
272
- &::marker { content: "#."; }
273
406
  }
274
407
 
275
408
  li span.diff {
276
- &::marker { content: unset; }
409
+ margin-bottom: 0;
410
+
277
411
  &::before {
278
- top: -2px;
279
412
  left: -$comparison-sidebar-offset + $steps-list-offset;
280
413
  height: 100%;
281
414
  width: $comparison-sidebar-width;
282
- min-height: 1.6em;
283
- }
284
- &::after {
285
- top: -2px;
286
- left: -$comparison-sidebar-padding + $steps-list-offset;
287
- min-height: 1.6em;
415
+ min-height: auto; // 1.6em;
288
416
  }
289
417
  }
290
418
  }
291
419
  }
292
420
 
293
421
  // Table-specific overrides
294
- $table-row-offset: -2px;
422
+ $table-row-offset: -2px;
295
423
 
296
424
  table {
297
425
  overflow-x: visible;
298
426
  }
299
427
 
428
+ // These elements are generated before new and removed dtables
429
+ // We need to remove them from the display and
430
+ // style the tables that follows them as a new/removed element
431
+ & > span.diff.ins {
432
+ display: none;
433
+
434
+ & + table {
435
+ @include diff-block;
436
+
437
+ &:before {
438
+ content: "+";
439
+ }
440
+ }
441
+ }
442
+
443
+ & > span.diff.del {
444
+ display: none;
445
+
446
+ & + table {
447
+ @include diff-block;
448
+
449
+ background: $removed-color;
450
+
451
+ &:before {
452
+ content: "−";
453
+ background: $removed-color;
454
+ }
455
+ }
456
+ }
457
+
300
458
  tr.diff {
301
459
  position: static;
302
- display: table-row;
303
460
  transform: scale(1);
304
461
 
462
+ &.del, &.ins {
463
+ display: table-row;
464
+ }
465
+
305
466
  &.del::after, &.ins::after {
306
467
  left: -$comparison-sidebar-padding + $table-row-offset;
307
468
  // Need to account for border in row element
@@ -331,12 +492,14 @@ $comparison-sidebar-offset: $comparison-sidebar-width + $comparison-sidebar-padd
331
492
  color: $text-colour;
332
493
  background-color: $diff-marker-removed-color;
333
494
  content: "−";
495
+ font-weight: normal;
334
496
  }
335
497
 
336
498
  &.ins td:first-child::before, &.ins th:first-child::before {
337
499
  color: $text-colour;
338
500
  background-color: $diff-marker-added-color;
339
501
  content: "+";
502
+ font-weight: normal;
340
503
  }
341
504
  }
342
505
  }
@@ -43,18 +43,18 @@ module Nokodiff
43
43
  append_accumulated_text(before_fragment, accumulated_before_text)
44
44
  append_accumulated_text(after_fragment, accumulated_after_text)
45
45
 
46
- before_fragment.add_child(highlight_changes(change.old_element, before_fragment))
47
- after_fragment.add_child(highlight_changes(change.new_element, after_fragment))
46
+ before_fragment.add_child(wrap_character_as_change(change.old_element, before_fragment))
47
+ after_fragment.add_child(wrap_character_as_change(change.new_element, after_fragment))
48
48
  end
49
49
 
50
50
  def emphasise_deletion(change)
51
51
  append_accumulated_text(before_fragment, accumulated_before_text)
52
- before_fragment.add_child(highlight_changes(change.old_element, before_fragment))
52
+ before_fragment.add_child(wrap_character_as_change(change.old_element, before_fragment))
53
53
  end
54
54
 
55
55
  def emphasise_addition(change)
56
56
  append_accumulated_text(after_fragment, accumulated_after_text)
57
- after_fragment.add_child(highlight_changes(change.new_element, after_fragment))
57
+ after_fragment.add_child(wrap_character_as_change(change.new_element, after_fragment))
58
58
  end
59
59
 
60
60
  def append_accumulated_text(fragment, accumulated_text)
@@ -135,7 +135,7 @@ module Nokodiff
135
135
  node.children.each_cons(2) do |left, right|
136
136
  next unless node_is_a_change?(left) && node_is_a_change?(right)
137
137
 
138
- left.content = left.content + right.content
138
+ left.children += right.children
139
139
  right.remove
140
140
 
141
141
  merge_adjacent_highlighted_changes(node)
@@ -1,12 +1,22 @@
1
1
  module Nokodiff
2
2
  module FormattingHelpers
3
- def highlight_changes(char, fragment)
3
+ def wrap_character_as_change(char, fragment)
4
4
  Nokogiri::XML::Node.new("span", fragment.document).tap do |n|
5
5
  n.content = char
6
6
  n["class"] = "diff-marker"
7
7
  end
8
8
  end
9
9
 
10
+ def wrap_node_as_change(node)
11
+ return unless node
12
+
13
+ wrapper = Nokogiri::XML::Node.new("span", node.document)
14
+ wrapper["class"] = "diff-marker"
15
+
16
+ node.replace(wrapper)
17
+ wrapper.add_child(node)
18
+ end
19
+
10
20
  def insert_table_row_change_marker(element, message)
11
21
  marker = Nokogiri::XML::Node.new("span", element.document)
12
22
  marker.content = "#{message} "
@@ -16,8 +16,10 @@ module Nokodiff
16
16
  attr_accessor :before_fragment, :after_fragment
17
17
 
18
18
  def diff_text_nodes(before_node, after_node)
19
- if before_node&.text? || after_node&.text?
19
+ if !contains_another_element?(before_node) && !contains_another_element?(after_node)
20
20
  diff_text_node_content(before_node, after_node)
21
+ elsif mixed_text_and_element_nodes(before_node, after_node)
22
+ mark_nodes_as_changed(before_node, after_node)
21
23
  elsif before_node&.element? || after_node&.element?
22
24
  before_children = before_node ? before_node.children.to_a : []
23
25
  after_children = after_node ? after_node.children.to_a : []
@@ -30,6 +32,19 @@ module Nokodiff
30
32
  end
31
33
  end
32
34
 
35
+ def contains_another_element?(node)
36
+ node && !node.text?
37
+ end
38
+
39
+ def mixed_text_and_element_nodes(before_node, after_node)
40
+ (before_node&.text? && after_node&.element?) || (before_node&.element? && after_node&.text?)
41
+ end
42
+
43
+ def mark_nodes_as_changed(before_node, after_node)
44
+ wrap_node_as_change(before_node)
45
+ wrap_node_as_change(after_node)
46
+ end
47
+
33
48
  def diff_text_node_content(before_text_node, after_text_node)
34
49
  before_chars = get_chars(before_text_node)
35
50
  after_chars = get_chars(after_text_node)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Nokodiff
4
- VERSION = "1.0.0.rc1"
4
+ VERSION = "1.1.0"
5
5
  end
data/lib/nokodiff.rb CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  require "nokogiri"
4
4
  require "diff-lcs"
5
- require "byebug"
6
5
 
7
6
  require_relative "nokodiff/formatting_helpers"
8
7
  require_relative "nokodiff/version"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nokodiff
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.rc1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - GOV.UK Dev
@@ -23,6 +23,20 @@ dependencies:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
25
  version: '0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: byebug
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
26
40
  - !ruby/object:Gem::Dependency
27
41
  name: rake
28
42
  requirement: !ruby/object:Gem::Requirement
@@ -93,40 +107,6 @@ dependencies:
93
107
  - - ">="
94
108
  - !ruby/object:Gem::Version
95
109
  version: '0'
96
- - !ruby/object:Gem::Dependency
97
- name: actionview
98
- requirement: !ruby/object:Gem::Requirement
99
- requirements:
100
- - - ">="
101
- - !ruby/object:Gem::Version
102
- version: '6'
103
- - - "<"
104
- - !ruby/object:Gem::Version
105
- version: 8.1.4
106
- type: :runtime
107
- prerelease: false
108
- version_requirements: !ruby/object:Gem::Requirement
109
- requirements:
110
- - - ">="
111
- - !ruby/object:Gem::Version
112
- version: '6'
113
- - - "<"
114
- - !ruby/object:Gem::Version
115
- version: 8.1.4
116
- - !ruby/object:Gem::Dependency
117
- name: byebug
118
- requirement: !ruby/object:Gem::Requirement
119
- requirements:
120
- - - ">="
121
- - !ruby/object:Gem::Version
122
- version: '0'
123
- type: :runtime
124
- prerelease: false
125
- version_requirements: !ruby/object:Gem::Requirement
126
- requirements:
127
- - - ">="
128
- - !ruby/object:Gem::Version
129
- version: '0'
130
110
  - !ruby/object:Gem::Dependency
131
111
  name: diff-lcs
132
112
  requirement: !ruby/object:Gem::Requirement
@@ -141,74 +121,6 @@ dependencies:
141
121
  - - ">="
142
122
  - !ruby/object:Gem::Version
143
123
  version: '0'
144
- - !ruby/object:Gem::Dependency
145
- name: gds-api-adapters
146
- requirement: !ruby/object:Gem::Requirement
147
- requirements:
148
- - - ">="
149
- - !ruby/object:Gem::Version
150
- version: '101.0'
151
- - - "<"
152
- - !ruby/object:Gem::Version
153
- version: '103.4'
154
- type: :runtime
155
- prerelease: false
156
- version_requirements: !ruby/object:Gem::Requirement
157
- requirements:
158
- - - ">="
159
- - !ruby/object:Gem::Version
160
- version: '101.0'
161
- - - "<"
162
- - !ruby/object:Gem::Version
163
- version: '103.4'
164
- - !ruby/object:Gem::Dependency
165
- name: govspeak
166
- requirement: !ruby/object:Gem::Requirement
167
- requirements:
168
- - - ">="
169
- - !ruby/object:Gem::Version
170
- version: 10.6.3
171
- type: :runtime
172
- prerelease: false
173
- version_requirements: !ruby/object:Gem::Requirement
174
- requirements:
175
- - - ">="
176
- - !ruby/object:Gem::Version
177
- version: 10.6.3
178
- - !ruby/object:Gem::Dependency
179
- name: rails
180
- requirement: !ruby/object:Gem::Requirement
181
- requirements:
182
- - - ">="
183
- - !ruby/object:Gem::Version
184
- version: '6'
185
- - - "<"
186
- - !ruby/object:Gem::Version
187
- version: 8.1.4
188
- type: :runtime
189
- prerelease: false
190
- version_requirements: !ruby/object:Gem::Requirement
191
- requirements:
192
- - - ">="
193
- - !ruby/object:Gem::Version
194
- version: '6'
195
- - - "<"
196
- - !ruby/object:Gem::Version
197
- version: 8.1.4
198
- - !ruby/object:Gem::Dependency
199
- name: view_component
200
- requirement: !ruby/object:Gem::Requirement
201
- requirements:
202
- - - "~>"
203
- - !ruby/object:Gem::Version
204
- version: '4'
205
- type: :runtime
206
- prerelease: false
207
- version_requirements: !ruby/object:Gem::Requirement
208
- requirements:
209
- - - "~>"
210
- - !ruby/object:Gem::Version
211
- version: '4'
212
124
  email:
213
125
  - govuk-dev@digital.cabinet-office.gov.uk
214
126
  executables: []
@@ -237,14 +149,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
237
149
  requirements:
238
150
  - - ">="
239
151
  - !ruby/object:Gem::Version
240
- version: '3.2'
152
+ version: '3.3'
241
153
  required_rubygems_version: !ruby/object:Gem::Requirement
242
154
  requirements:
243
155
  - - ">="
244
156
  - !ruby/object:Gem::Version
245
157
  version: '0'
246
158
  requirements: []
247
- rubygems_version: 4.0.16
159
+ rubygems_version: 4.0.22
248
160
  specification_version: 4
249
161
  summary: A Ruby Gem to highlight additions, deletions and character level changes
250
162
  while preserving original HTML