openstax_kitchen 15.0.0 → 16.0.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: 074dfc264ca97aab5805a3ab189b49fe1e97a1108366b592b5599a70e15f1345
4
- data.tar.gz: fee3491d899d7983e55e5c6eb22010b49d23e8dd43e54ca97950a7be2fbda93f
3
+ metadata.gz: 7796fb964e8a6ff796d9cf84220449681a89e5501e41e0a9a956620faf022d11
4
+ data.tar.gz: 4b2c488ac82a05067c7353f274b9f94888125eb7f66cfa92f30db3c28e7ae29a
5
5
  SHA512:
6
- metadata.gz: d9a5936f931cf6b1c3485543adf375426d71b444109c68fc80b0a06ef6f953e4ac43cd40b27941c06dec0541e02dd2b3387074aa8a956821cdca781f97607f1d
7
- data.tar.gz: 13d5bf302fe8144acef670f017bc8393847292d37f4a4dae68922cbf56c52da41c18719ec586ca1b5b1a135dc0c303e168f5515903e2b667299347cba909e7d4
6
+ metadata.gz: cc57439823f55ee6cdec35304a2bb4413a28afc5c98ae616effadec60095cfa964a4b9faa0380178f189c55771d1a1f28813268ce001349f29c3d1b44397d4ab
7
+ data.tar.gz: d055f27db123b8e7441f45056e1c6f2a576ab56d1faa3bbdbb4af6a904674f1562e4403dd5e914a372fe67c5e969eb385838aab6f9ff9a5cbc8a0f5b20356df7
data/CHANGELOG.md CHANGED
@@ -6,6 +6,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+
10
+ ## [16.0.0] - 2021-11-19
11
+
12
+ * Add reference link separator to `BakeReferences.v1` (patch)
13
+ * Modify `BakeFootnotes` to be more general (minor)
14
+ * Add `#preceded_by_text` method to element_base and the nokigiri patch (minor)
15
+ * Broaden caption selection for `BakeNumberedTable#v2` (patch)
16
+ * Add details of question count to injected exercises in `BakeInjectedExercise` (major)
17
+ * Add target labels to chapter content module pages option in `BakeNonIntroductionPages`, create a separate directory `BakeLOLinkLabels` to add `.label-text`, `.label-counter` spans wrappers for links with `.lo-reference` class (minor)
18
+ * Add `BakeScreenreaderSpans` direction (minor)
19
+ * Fix `BakeIndex` to group terms by character in polish books and transliterate it for others (minor)
20
+ * Add optional bake `exercies-context` figure_reference if there is one present in singular part exercises to `BakeInjectedExercise`,`BakeInjectedQuestion` to move it down from exercise to question problem container. (major)
21
+ * Create v3 for autotitled exercises with os-hasSolution class
22
+
9
23
  ## [15.0.0] - 2021-11-05
10
24
 
11
25
  * Add unstyled tables to `BakeTableBody` (minor)
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- openstax_kitchen (15.0.0)
4
+ openstax_kitchen (16.0.0)
5
5
  activesupport
6
6
  i18n
7
7
  nokogiri
@@ -99,7 +99,7 @@ GEM
99
99
  tins (~> 1.0)
100
100
  tins (1.26.0)
101
101
  sync
102
- twitter_cldr (6.7.0)
102
+ twitter_cldr (6.8.0)
103
103
  camertron-eprun
104
104
  cldr-plurals-runtime-rb (~> 1.1)
105
105
  tzinfo
@@ -10,6 +10,10 @@ module Kitchen
10
10
  def self.v2(exercise:, title:)
11
11
  V2.new.bake(exercise: exercise, title: title)
12
12
  end
13
+
14
+ def self.v3(exercise:, title:)
15
+ V3.new.bake(exercise: exercise, title: title)
16
+ end
13
17
  end
14
18
  end
15
19
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen::Directions::BakeAutotitledExercise
4
+ # Differences from V2:
5
+ # 1. Exercise with solution has class os-hasSolution
6
+ # 2. Solution id is based on exercise id
7
+ class V3
8
+ def bake(exercise:, title:)
9
+ exercise.add_class('unnumbered')
10
+ exercise.titles.first&.trash
11
+
12
+ # bake problem
13
+ exercise.prepend(child:
14
+ <<~HTML
15
+ <h3 class="os-title" data-type="title">
16
+ <span class="os-title-label">#{title}</span>
17
+ </h3>
18
+ HTML
19
+ )
20
+ exercise.problem.wrap_children(class: 'os-problem-container')
21
+ return unless exercise.solution
22
+
23
+ exercise.add_class('os-hasSolution')
24
+ exercise.solution.id = "#{exercise.id}-solution"
25
+ exercise.solution.wrap_children(class: 'os-solution-container')
26
+ exercise.solution.prepend(child:
27
+ <<~HTML
28
+ <h4 class="solution-title" data-type="title">
29
+ <span class="os-text">#{I18n.t(:solution)}</span>
30
+ </h4>
31
+ HTML
32
+ )
33
+ end
34
+ end
35
+ end
@@ -30,7 +30,7 @@ module Kitchen::Directions::BakeFootnotes
30
30
  aside_id_to_footnote_number[aside_id] = footnote_number
31
31
  if anchor.parent.name == 'p'
32
32
  anchor.parent.add_class('has-noteref')
33
- elsif anchor.parent.name == 'em' && anchor.parent.parent.name == 'p'
33
+ elsif anchor.parent.name != 'p' && anchor.parent.parent.name == 'p'
34
34
  anchor.parent.parent.add_class('has-noteref')
35
35
  end
36
36
  end
@@ -165,7 +165,7 @@ module Kitchen::Directions::BakeIndex
165
165
  group_by = term_reference[0]
166
166
  content = term_reference
167
167
  else
168
- group_by = I18n.transliterate(term_element.text.strip[0])
168
+ group_by = I18n.character_to_group(term_element.text.strip[0])
169
169
  content = term_element.text
170
170
  end
171
171
 
@@ -7,12 +7,21 @@ module Kitchen::Directions::BakeInjectedExercise
7
7
 
8
8
  class V1
9
9
  def bake(exercise:)
10
- context = exercise.search('div[data-type="exercise-context"]')&.first
10
+ question_count = exercise.injected_questions.count
11
+ exercise[:'data-question-count'] = question_count
12
+ exercise[:'data-is-multipart'] = question_count > 1 ? 'True' : 'False'
13
+
14
+ context = exercise&.exercise_context
15
+
11
16
  return unless context
12
17
 
13
18
  # link replacement is done by BakeLinkPlaceholders
14
19
  link = context.first('a').cut
15
20
  context.replace_children(with: "#{I18n.t(:context_lead_text)}#{link.paste}")
21
+ return unless question_count == 1
22
+
23
+ question = exercise.exercise_question
24
+ question.prepend(child: context.cut.paste)
16
25
  end
17
26
  end
18
27
  end
@@ -41,11 +41,15 @@ module Kitchen::Directions::BakeInjectedExerciseQuestion
41
41
  end
42
42
  end
43
43
 
44
+ context = question.exercise_context_in_question&.cut&.paste
45
+
44
46
  question.prepend(child:
45
47
  <<~HTML
46
48
  #{problem_number unless only_number_solution}
47
49
  #{"<span class='os-divider'>. </span>" unless only_number_solution}
48
50
  <div class="os-problem-container">
51
+ #{context if context.present?}
52
+ #{"<span class='os-divider'>. </span>" if context.present?}
49
53
  #{question.stimulus&.cut&.paste}
50
54
  #{question.stem.cut.paste}
51
55
  #{question.answers&.cut&.paste}
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen
4
+ module Directions
5
+ # Bake directions for LO link labels
6
+ module BakeLOLinkLabels
7
+ def self.v1(book:)
8
+ book.search('a.lo-reference').each do |anchor|
9
+ anchor.wrap_children('span', class: 'label-counter')
10
+ anchor.prepend(child:
11
+ <<~HTML
12
+ <span class="label-text">#{I18n.t(:lo_label_text)}</span>
13
+ HTML
14
+ )
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -3,13 +3,15 @@
3
3
  module Kitchen
4
4
  module Directions
5
5
  module BakeNonIntroductionPages
6
- def self.v1(chapter:)
6
+ def self.v1(chapter:, add_target_label: false)
7
7
  chapter.non_introduction_pages.each do |page|
8
8
  number = "#{chapter.count_in(:book)}.#{page.count_in(:chapter)}"
9
9
 
10
10
  page.search("div[data-type='description']").each(&:trash)
11
11
  page.add_class('chapter-content-module')
12
12
 
13
+ page.target_label(custom_content: number) if add_target_label
14
+
13
15
  title = page.title
14
16
  title.name = 'h2'
15
17
  title.replace_children(with:
@@ -9,7 +9,8 @@ module Kitchen::Directions::BakeNumberedTable
9
9
  Kitchen::Directions::BakeTableBody::V1.new.bake(table: table, number: number, cases: cases)
10
10
 
11
11
  caption = ''
12
- if table&.caption&.first("span[data-type='title']") && !table.top_captioned?
12
+ if (table&.caption&.first("span[data-type='title']") || table&.caption) \
13
+ && !table.top_captioned?
13
14
  caption_el = table.caption
14
15
  caption_el.add_class('os-caption')
15
16
  caption_el.name = 'span'
@@ -12,6 +12,19 @@ module Kitchen::Directions::BakeReferences
12
12
  <sup class="os-citation-number">#{link.count_in(:chapter)}</sup>
13
13
  HTML
14
14
  )
15
+
16
+ next if link.nil?
17
+
18
+ link_sibling = link.previous unless link.preceded_by_text?
19
+ next if link_sibling.nil?
20
+
21
+ next unless link_sibling&.raw&.attr('data-type') == 'cite'
22
+
23
+ link.prepend(sibling:
24
+ <<~HTML
25
+ <span class="os-reference-link-separator">, </span>
26
+ HTML
27
+ )
15
28
  end
16
29
 
17
30
  chapter.references.each do |reference|
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen
4
+ module Directions
5
+ module BakeScreenreaderSpans
6
+ # Add text for accessibility.
7
+ # Additional screenreader spans can be added below.
8
+ def self.v1(book:)
9
+ book.search('u[data-effect="double-underline"]').each do |element|
10
+ element.add_previous_sibling(
11
+ '<span data-screenreader-only="true">double underline</span>'
12
+ )
13
+ end
14
+ book.search('u[data-effect="underline"]').each do |element|
15
+ element.add_previous_sibling(
16
+ '<span data-screenreader-only="true">underline</span>'
17
+ )
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -82,9 +82,13 @@ module Kitchen
82
82
  # Set the inner HTML for this element
83
83
  # @see https://www.rubydoc.info/github/sparklemotion/nokogiri/Nokogiri/XML/Node#inner_html=-instance_method Nokogiri::XML::Node#inner_html=
84
84
  # @return Object
85
+ # @!method preceded_by_text
86
+ # Returns true if the immediately preceding sibling is text
87
+ # @return Boolean
85
88
  def_delegators :@node, :name=, :name, :[], :[]=, :add_class, :remove_class,
86
89
  :text, :wrap, :children, :to_html, :remove_attribute,
87
- :key?, :classes, :path, :inner_html=
90
+ :key?, :classes, :path, :inner_html=, :add_previous_sibling,
91
+ :preceded_by_text?
88
92
 
89
93
  # @!method config
90
94
  # Get the config for this element's document
@@ -502,8 +506,8 @@ module Kitchen
502
506
  Element.new(node: raw.parent, document: document, short_type: "parent(#{short_type})")
503
507
  end
504
508
 
505
- # returns previous element
506
- # skips double indentations that the nokigiri sometimes picks up
509
+ # returns previous element sibling
510
+ # (only returns elements or nil)
507
511
  # nil if there's no previous sibling
508
512
  #
509
513
  def previous
@@ -754,7 +758,7 @@ module Kitchen
754
758
  def_delegators :as_enumerator, :pages, :chapters, :terms, :figures, :notes, :tables, :examples,
755
759
  :metadatas, :non_introduction_pages, :units, :titles, :exercises, :references,
756
760
  :composite_pages, :composite_chapters, :solutions, :injected_questions,
757
- :search_with, :sections
761
+ :search_with, :sections, :injected_exercises
758
762
 
759
763
  # Returns this element as an enumerator (over only one element, itself)
760
764
  #
@@ -336,6 +336,24 @@ module Kitchen
336
336
  css_or_xpath: css_or_xpath, only: only, except: except)
337
337
  end
338
338
 
339
+ # Returns an enumerator that iterates through injected exercises within the scope of this enumerator
340
+ #
341
+ # @param css_or_xpath [String] additional selectors to further narrow the element iterated over;
342
+ # a "$" in this argument will be replaced with the default selector for the element being
343
+ # iterated over.
344
+ # @param only [Symbol, Callable] the name of a method to call on an element or a
345
+ # lambda or proc that accepts an element; elements will only be included in the
346
+ # search results if the method or callable returns true
347
+ # @param except [Symbol, Callable] the name of a method to call on an element or a
348
+ # lambda or proc that accepts an element; elements will not be included in the
349
+ # search results if the method or callable returns false
350
+ #
351
+ def injected_exercises(css_or_xpath=nil, only: nil, except: nil)
352
+ block_error_if(block_given?)
353
+ chain_to(InjectedExerciseElementEnumerator,
354
+ css_or_xpath: css_or_xpath, only: only, except: except)
355
+ end
356
+
339
357
  # Returns an enumerator that iterates within the scope of this enumerator
340
358
  #
341
359
  # @param css_or_xpath [String] additional selectors to further narrow the element iterated over
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen
4
+ # An element for an example
5
+ #
6
+ class InjectedExerciseElement < ElementBase
7
+
8
+ # Creates a new +InjectedQuestionElement+
9
+ #
10
+ # @param node [Nokogiri::XML::Node] the node this element wraps
11
+ # @param document [Document] this element's document
12
+ #
13
+ def initialize(node:, document: nil)
14
+ super(node: node,
15
+ document: document,
16
+ enumerator_class: InjectedExerciseElementEnumerator)
17
+ end
18
+
19
+ # Returns the short type
20
+ # @return [Symbol]
21
+ #
22
+ def self.short_type
23
+ :injected_exercise
24
+ end
25
+
26
+ # Returns the exercise context element.
27
+ # @return [Element]
28
+ #
29
+ def exercise_context
30
+ first("div[data-type='exercise-context']")
31
+ end
32
+
33
+ # Returns the exercise question element.
34
+ # @return [Element]
35
+ #
36
+ def exercise_question
37
+ first("div[data-type='exercise-question']")
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kitchen
4
+ # An enumerator for example elements
5
+ #
6
+ class InjectedExerciseElementEnumerator < ElementEnumeratorBase
7
+
8
+ # Returns a factory for this enumerator
9
+ #
10
+ # @return [ElementEnumeratorFactory]
11
+ #
12
+ def self.factory
13
+ ElementEnumeratorFactory.new(
14
+ default_css_or_xpath: Selector.named(:injected_exercise),
15
+ sub_element_class: InjectedExerciseElement,
16
+ enumerator_class: self
17
+ )
18
+ end
19
+
20
+ end
21
+ end
@@ -55,6 +55,13 @@ module Kitchen
55
55
  first("div[data-type='question-solution']")
56
56
  end
57
57
 
58
+ # Returns the exercise context element.
59
+ # @return [Element]
60
+ #
61
+ def exercise_context_in_question
62
+ first("div[data-type='exercise-context']")
63
+ end
64
+
58
65
  # Returns the answer correctness given an alphabet
59
66
  #
60
67
  # @return [Array]
@@ -4,6 +4,10 @@ require 'twitter_cldr'
4
4
 
5
5
  # rubocop:disable Style/Documentation
6
6
  module I18n
7
+ def self.character_to_group(character)
8
+ I18n.locale == :pl ? character : I18n.transliterate(character)
9
+ end
10
+
7
11
  def self.sort_strings(first, second)
8
12
  string_sorter.compare(first, second)
9
13
  end
@@ -74,6 +74,14 @@ module Nokogiri
74
74
  prev.text? ? prev.previous : prev
75
75
  end
76
76
 
77
+ def preceded_by_text?
78
+ prev = previous_sibling
79
+ while !prev.nil? && prev.blank? do prev = prev.previous_sibling end
80
+ return false if prev.nil?
81
+
82
+ prev.text?
83
+ end
84
+
77
85
  def self.selector_to_css_nodes(selector)
78
86
  # No need to parse the same selector more than once.
79
87
  @parsed_selectors ||= {}
@@ -65,6 +65,9 @@ module Kitchen
65
65
  # Selector for a section
66
66
  # @return [String]
67
67
  attr_accessor :section
68
+ # Selector for an injected exercise
69
+ # @return [String]
70
+ attr_accessor :injected_exercise
68
71
 
69
72
  # Override specific selectors
70
73
  #
@@ -30,6 +30,7 @@ module Kitchen
30
30
  "div[data-type='question-solution']"
31
31
  self.injected_question = "div[data-type='exercise-question']"
32
32
  self.section = 'section'
33
+ self.injected_exercise = "div[data-type='injected-exercise']"
33
34
  end
34
35
 
35
36
  end
@@ -3,5 +3,5 @@
3
3
  # A library for modifying the structure of OpenStax book XML.
4
4
  #
5
5
  module Kitchen
6
- VERSION = '15.0.0'
6
+ VERSION = '16.0.0'
7
7
  end
data/lib/locales/en.yml CHANGED
@@ -28,6 +28,7 @@ en:
28
28
  iframe_link_text: Click to view content
29
29
  handbook_outline_title: Outline
30
30
  context_lead_text: 'Refer to '
31
+ lo_label_text: 'LO '
31
32
  eoc:
32
33
  glossary: Key Terms
33
34
  key-equations: Key Equations
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: openstax_kitchen
3
3
  version: !ruby/object:Gem::Version
4
- version: 15.0.0
4
+ version: 16.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - JP Slavinsky
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-11-05 00:00:00.000000000 Z
11
+ date: 2021-11-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -252,6 +252,7 @@ files:
252
252
  - lib/kitchen/directions/bake_autotitled_exercise/main.rb
253
253
  - lib/kitchen/directions/bake_autotitled_exercise/v1.rb
254
254
  - lib/kitchen/directions/bake_autotitled_exercise/v2.rb
255
+ - lib/kitchen/directions/bake_autotitled_exercise/v3.rb
255
256
  - lib/kitchen/directions/bake_chapter_glossary/main.rb
256
257
  - lib/kitchen/directions/bake_chapter_glossary/v1.rb
257
258
  - lib/kitchen/directions/bake_chapter_introductions/bake_chapter_objectives.rb
@@ -296,13 +297,14 @@ files:
296
297
  - lib/kitchen/directions/bake_index/main.rb
297
298
  - lib/kitchen/directions/bake_index/v1.rb
298
299
  - lib/kitchen/directions/bake_index/v1.xhtml.erb
299
- - lib/kitchen/directions/bake_injected_exercise.rb
300
300
  - lib/kitchen/directions/bake_injected_exercise/add_injected_exercise_id.rb
301
+ - lib/kitchen/directions/bake_injected_exercise/bake_injected_exercise.rb
301
302
  - lib/kitchen/directions/bake_injected_exercise/bake_injected_exercise_question.rb
302
303
  - lib/kitchen/directions/bake_inline_lists.rb
303
304
  - lib/kitchen/directions/bake_learning_objectives.rb
304
305
  - lib/kitchen/directions/bake_link_placeholders.rb
305
306
  - lib/kitchen/directions/bake_lists_with_para.rb
307
+ - lib/kitchen/directions/bake_lo_link_labels.rb
306
308
  - lib/kitchen/directions/bake_math_in_paragraph.rb
307
309
  - lib/kitchen/directions/bake_non_introduction_pages.rb
308
310
  - lib/kitchen/directions/bake_notes/bake_autotitled_notes.rb
@@ -326,6 +328,7 @@ files:
326
328
  - lib/kitchen/directions/bake_references/v1.rb
327
329
  - lib/kitchen/directions/bake_references/v2.rb
328
330
  - lib/kitchen/directions/bake_references/v3.rb
331
+ - lib/kitchen/directions/bake_screenreader_spans.rb
329
332
  - lib/kitchen/directions/bake_stepwise.rb
330
333
  - lib/kitchen/directions/bake_suggested_reading.rb
331
334
  - lib/kitchen/directions/bake_toc.rb
@@ -373,6 +376,8 @@ files:
373
376
  - lib/kitchen/figure_element_enumerator.rb
374
377
  - lib/kitchen/i18n_string.rb
375
378
  - lib/kitchen/id_tracker.rb
379
+ - lib/kitchen/injected_exercise_element.rb
380
+ - lib/kitchen/injected_exercise_element_enumerator.rb
376
381
  - lib/kitchen/injected_question_element.rb
377
382
  - lib/kitchen/injected_question_element_enumerator.rb
378
383
  - lib/kitchen/metadata_element.rb