openstax_kitchen 2.0.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (133) hide show
  1. checksums.yaml +4 -4
  2. data/.devcontainer/devcontainer.json +37 -17
  3. data/.github/config.yml +14 -0
  4. data/.github/workflows/tests.yml +5 -15
  5. data/.gitignore +1 -1
  6. data/.inch.yml +6 -0
  7. data/.rubocop.yml +65 -0
  8. data/CHANGELOG.md +16 -0
  9. data/Gemfile +5 -3
  10. data/Gemfile.lock +54 -5
  11. data/README.md +58 -11
  12. data/Rakefile +5 -3
  13. data/bin/console +4 -3
  14. data/docker/Dockerfile +36 -0
  15. data/docker/Dockerfile.ci +10 -0
  16. data/docker/bash +5 -1
  17. data/docker/build +10 -0
  18. data/docker/ci +16 -0
  19. data/docker/run +9 -0
  20. data/docker/tag_and_push_latest +17 -0
  21. data/lefthook.yml +6 -0
  22. data/lib/kitchen/ancestor.rb +38 -1
  23. data/lib/kitchen/book_document.rb +20 -2
  24. data/lib/kitchen/book_element.rb +24 -3
  25. data/lib/kitchen/book_element_enumerator.rb +4 -0
  26. data/lib/kitchen/book_recipe.rb +15 -1
  27. data/lib/kitchen/chapter_element.rb +43 -3
  28. data/lib/kitchen/chapter_element_enumerator.rb +9 -1
  29. data/lib/kitchen/clipboard.rb +35 -4
  30. data/lib/kitchen/composite_chapter_element.rb +20 -1
  31. data/lib/kitchen/composite_page_element.rb +25 -2
  32. data/lib/kitchen/composite_page_element_enumerator.rb +8 -0
  33. data/lib/kitchen/config.rb +14 -7
  34. data/lib/kitchen/counter.rb +9 -2
  35. data/lib/kitchen/debug/print_recipe_error.rb +53 -35
  36. data/lib/kitchen/directions/.rubocop.yml +22 -0
  37. data/lib/kitchen/directions/bake_appendix.rb +4 -4
  38. data/lib/kitchen/directions/bake_chapter_glossary.rb +10 -7
  39. data/lib/kitchen/directions/bake_chapter_introductions.rb +6 -6
  40. data/lib/kitchen/directions/bake_chapter_key_equations.rb +9 -6
  41. data/lib/kitchen/directions/bake_chapter_summary.rb +16 -13
  42. data/lib/kitchen/directions/bake_chapter_title/main.rb +11 -0
  43. data/lib/kitchen/directions/bake_chapter_title/v1.rb +24 -0
  44. data/lib/kitchen/directions/bake_composite_pages.rb +2 -2
  45. data/lib/kitchen/directions/bake_example.rb +6 -4
  46. data/lib/kitchen/directions/bake_exercises/main.rb +11 -0
  47. data/lib/kitchen/directions/bake_exercises/v1.rb +166 -0
  48. data/lib/kitchen/directions/bake_figure.rb +8 -5
  49. data/lib/kitchen/directions/bake_footnotes/main.rb +2 -2
  50. data/lib/kitchen/directions/bake_footnotes/v1.rb +4 -4
  51. data/lib/kitchen/directions/bake_index/main.rb +2 -2
  52. data/lib/kitchen/directions/bake_index/v1.rb +22 -15
  53. data/lib/kitchen/directions/bake_link_placeholders.rb +24 -0
  54. data/lib/kitchen/directions/bake_math_in_paragraph.rb +5 -3
  55. data/lib/kitchen/directions/bake_notes.rb +8 -8
  56. data/lib/kitchen/directions/bake_numbered_table/main.rb +2 -2
  57. data/lib/kitchen/directions/bake_numbered_table/v1.rb +21 -16
  58. data/lib/kitchen/directions/bake_page_abstracts.rb +14 -0
  59. data/lib/kitchen/directions/bake_preface/main.rb +11 -0
  60. data/lib/kitchen/directions/bake_preface/v1.rb +18 -0
  61. data/lib/kitchen/directions/bake_stepwise.rb +7 -7
  62. data/lib/kitchen/directions/bake_suggested_reading.rb +26 -0
  63. data/lib/kitchen/directions/bake_toc.rb +41 -22
  64. data/lib/kitchen/directions/bake_unit_title/main.rb +11 -0
  65. data/lib/kitchen/directions/bake_unit_title/v1.rb +23 -0
  66. data/lib/kitchen/directions/bake_unnumbered_tables.rb +7 -5
  67. data/lib/kitchen/directions/move_title_text_into_span.rb +2 -2
  68. data/lib/kitchen/document.rb +72 -13
  69. data/lib/kitchen/element.rb +11 -0
  70. data/lib/kitchen/element_base.rb +276 -56
  71. data/lib/kitchen/element_enumerator.rb +8 -0
  72. data/lib/kitchen/element_enumerator_base.rb +210 -28
  73. data/lib/kitchen/element_enumerator_factory.rb +59 -52
  74. data/lib/kitchen/element_factory.rb +27 -12
  75. data/lib/kitchen/errors.rb +5 -0
  76. data/lib/kitchen/example_element.rb +19 -1
  77. data/lib/kitchen/example_element_enumerator.rb +9 -1
  78. data/lib/kitchen/figure_element.rb +36 -2
  79. data/lib/kitchen/figure_element_enumerator.rb +9 -1
  80. data/lib/kitchen/metadata_element.rb +28 -0
  81. data/lib/kitchen/metadata_element_enumerator.rb +21 -0
  82. data/lib/kitchen/mixins/block_error_if.rb +24 -4
  83. data/lib/kitchen/note_element.rb +37 -7
  84. data/lib/kitchen/note_element_enumerator.rb +9 -1
  85. data/lib/kitchen/oven.rb +66 -15
  86. data/lib/kitchen/page_element.rb +62 -13
  87. data/lib/kitchen/page_element_enumerator.rb +9 -1
  88. data/lib/kitchen/pantry.rb +28 -1
  89. data/lib/kitchen/patches/nokogiri.rb +19 -2
  90. data/lib/kitchen/patches/renderable.rb +9 -3
  91. data/lib/kitchen/patches/string.rb +8 -0
  92. data/lib/kitchen/recipe.rb +38 -34
  93. data/lib/kitchen/search_history.rb +43 -4
  94. data/lib/kitchen/search_query.rb +84 -0
  95. data/lib/kitchen/selectors/base.rb +26 -0
  96. data/lib/kitchen/selectors/standard_1.rb +8 -0
  97. data/lib/kitchen/table_element.rb +54 -3
  98. data/lib/kitchen/table_element_enumerator.rb +9 -1
  99. data/lib/kitchen/term_element.rb +15 -1
  100. data/lib/kitchen/term_element_enumerator.rb +9 -1
  101. data/lib/kitchen/transliterations.rb +7 -5
  102. data/lib/kitchen/type_casting_element_enumerator.rb +17 -1
  103. data/lib/kitchen/unit_element.rb +39 -0
  104. data/lib/kitchen/unit_element_enumerator.rb +20 -0
  105. data/lib/kitchen/utils.rb +10 -13
  106. data/lib/kitchen/version.rb +5 -1
  107. data/lib/locales/en.yml +6 -0
  108. data/lib/openstax_kitchen.rb +43 -42
  109. data/openstax_kitchen.gemspec +26 -20
  110. data/tutorials/00/solution1.rb +9 -0
  111. data/tutorials/00/solution2.rb +8 -0
  112. data/tutorials/01/solution1.rb +18 -0
  113. data/tutorials/01/solution2.rb +26 -0
  114. data/tutorials/02/solution1.rb +31 -0
  115. data/tutorials/03/{solution_1.rb → solution1.rb} +6 -4
  116. data/tutorials/03/solution2.rb +18 -0
  117. data/tutorials/04/{solution_1.rb → solution1.rb} +4 -2
  118. data/tutorials/04/{solution_2.rb → solution2.rb} +6 -4
  119. data/tutorials/05/solution1.rb +11 -0
  120. data/tutorials/check_it +16 -15
  121. data/tutorials/setup_my_recipes +7 -6
  122. metadata +101 -22
  123. data/Dockerfile +0 -19
  124. data/docker-compose.yml +0 -12
  125. data/docker/entrypoint +0 -9
  126. data/lib/kitchen/directions/bake_exercises.rb +0 -164
  127. data/tutorials/00/solution_1.rb +0 -7
  128. data/tutorials/00/solution_2.rb +0 -6
  129. data/tutorials/01/solution_1.rb +0 -16
  130. data/tutorials/01/solution_2.rb +0 -24
  131. data/tutorials/02/solution_1.rb +0 -29
  132. data/tutorials/03/solution_2.rb +0 -15
  133. data/tutorials/05/solution_1.rb +0 -9
data/Rakefile CHANGED
@@ -1,6 +1,8 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
3
5
 
4
6
  RSpec::Core::RakeTask.new(:spec)
5
7
 
6
- task :default => :spec
8
+ task default: :spec
data/bin/console CHANGED
@@ -1,7 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- require "bundler/setup"
4
- require "openstax_kitchen"
4
+ require 'bundler/setup'
5
+ require 'openstax_kitchen'
5
6
 
6
7
  # You can add fixtures and/or initialization code here to make experimenting
7
8
  # with your gem easier. You can also use a different console, if you like.
@@ -10,5 +11,5 @@ require "openstax_kitchen"
10
11
  # require "pry"
11
12
  # Pry.start
12
13
 
13
- require "irb"
14
+ require 'irb'
14
15
  IRB.start(__FILE__)
data/docker/Dockerfile ADDED
@@ -0,0 +1,36 @@
1
+ FROM ruby:2.6-slim
2
+
3
+ ARG bundler_version
4
+
5
+ RUN apt-get update && \
6
+ apt-get install -y --no-install-recommends \
7
+ git \
8
+ vim \
9
+ openssh-server \
10
+ build-essential \
11
+ wget \
12
+ && rm -rf /var/lib/apt/lists/*
13
+
14
+ # Install a quick colorized prompt and turn on ls coloring
15
+ RUN git clone https://github.com/nojhan/liquidprompt.git ~/liquidprompt && \
16
+ echo '[[ $- = *i* ]] && source ~/liquidprompt/liquidprompt' >>~/.bashrc && \
17
+ mkdir -p ~/.config && \
18
+ echo 'export LP_HOSTNAME_ALWAYS=1' >>~/.config/liquidpromptrc && \
19
+ echo 'export LP_USER_ALWAYS=-1' >>~/.config/liquidpromptrc && \
20
+ sed -i "/color=auto/"' s/# //' ~/.bashrc && \
21
+ sed -i "/alias ls/,/lA/"' s/# //' ~/.bashrc
22
+
23
+ # VSCode Live Share libraries
24
+ RUN wget -O ~/vsls-reqs https://aka.ms/vsls-linux-prereq-script && chmod +x ~/vsls-reqs && ~/vsls-reqs
25
+
26
+ WORKDIR /code
27
+ COPY . /code/
28
+
29
+ RUN gem install bundler --no-document --version $bundler_version && \
30
+ gem install solargraph && \
31
+ gem install lefthook && \
32
+ bundle config set no-cache 'true' && \
33
+ bundle config set silence_root_warning 'true' && \
34
+ bundle install && \
35
+ echo "Generating YARD documentation for gems (this can be slow)..." && \
36
+ bundle exec yard gems --quiet
@@ -0,0 +1,10 @@
1
+ # Use non-slim to have git and build tools installed (faster for lots of runs
2
+ # on CI)
3
+ FROM ruby:2.6
4
+
5
+ ARG bundler_version
6
+
7
+ RUN gem install bundler --no-document --version $bundler_version
8
+
9
+ WORKDIR /code
10
+ COPY . /code/
data/docker/bash CHANGED
@@ -1 +1,5 @@
1
- docker-compose exec app bash
1
+ #!/usr/bin/env bash
2
+
3
+ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
4
+
5
+ $DIR/run /bin/bash
data/docker/build ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env bash
2
+
3
+ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
4
+
5
+ if [ "$1" == "--ci" ]; then SUFFIX=".ci"; else SUFFIX=""; fi
6
+
7
+ docker build -f $DIR/Dockerfile$SUFFIX \
8
+ -t openstax/kitchen$SUFFIX:latest \
9
+ --build-arg bundler_version=2.2.4 \
10
+ $DIR/..
data/docker/ci ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env bash
2
+
3
+ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
4
+
5
+ # See https://docs.codecov.io/docs/testing-with-docker, also note that it is
6
+ # critical to set CI=true because codecov-ruby won't detect GitHub Actions
7
+ # without it per:
8
+ # https://github.com/codecov/codecov-ruby/blob/484767f1c3d7992a9d7fedd6dc72d35a80d04f70/lib/codecov.rb#L68-L69
9
+
10
+ docker run $CI_ENV \
11
+ -e ENABLE_CODECOV=1 -e CI=true \
12
+ -v $DIR/..:/code \
13
+ -v vendor/bundle \
14
+ -w /code \
15
+ openstax/kitchen.ci:latest \
16
+ /bin/bash -c "bundle config path vendor/bundle; bundle install; bundle exec rspec"
data/docker/run ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env bash
2
+
3
+ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
4
+
5
+ docker run -it \
6
+ -v $DIR/..:/code \
7
+ -w /code \
8
+ openstax/kitchen:latest \
9
+ "$@"
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env bash
2
+
3
+ TAG="docker tag openstax/kitchen:latest openstax/kitchen:$1"
4
+ PUSH="docker push openstax/kitchen:$1"
5
+
6
+ echo "About to run the following:"
7
+ echo $TAG
8
+ echo $PUSH
9
+
10
+ read -p "Are you sure? (Y/n) " -r
11
+ echo # (optional) move to a new line
12
+ if [[ $REPLY =~ ^[Yy]$ ]]
13
+ then
14
+ $TAG
15
+ echo Tagged!
16
+ $PUSH
17
+ fi
data/lefthook.yml ADDED
@@ -0,0 +1,6 @@
1
+ pre-push:
2
+ commands:
3
+ rubocop:
4
+ files: git diff --name-only main
5
+ glob: "*.rb"
6
+ run: bundle exec rubocop {files} --disable-pending-cops
@@ -1,28 +1,65 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kitchen
4
+ # A wrapper for an element representing an ancestor (up the DOM tree) of another
5
+ # element; keeps track of the number of descendants it has of a particular type
6
+ #
2
7
  class Ancestor
3
8
 
4
- attr_accessor :type
9
+ # The type, e.g. +:page+, +:term+
10
+ # @return [Symbol] the type
11
+ #
12
+ attr_reader :type
13
+
14
+ # The ancestor element
15
+ # @return [ElementBase] the ancestor element
16
+ #
5
17
  attr_accessor :element
6
18
 
19
+ # Create a new Ancestor
20
+ #
21
+ # @param element [ElementBase] the ancestor element
22
+ #
7
23
  def initialize(element)
8
24
  @element = element
9
25
  @type = element.short_type
10
26
  @descendant_counts = {}
11
27
  end
12
28
 
29
+ # Adds 1 to the descendant count for the given type
30
+ #
31
+ # @param descendant_type [String, Symbol] the descendent's type
32
+ #
13
33
  def increment_descendant_count(descendant_type)
14
34
  @descendant_counts[descendant_type.to_sym] = get_descendant_count(descendant_type) + 1
15
35
  end
16
36
 
37
+ # Decreases the descendant count for the given type by some amount
38
+ #
39
+ # @param descendant_type [String, Symbol] the descendent's type
40
+ # @param by [Integer] the amount by which to decrement
41
+ # @raise [RangeError] if descendant count is a negative number
42
+ #
17
43
  def decrement_descendant_count(descendant_type, by: 1)
44
+ raise(RangeError, 'An element cannot have negative descendants') \
45
+ if (get_descendant_count(descendant_type) - by).negative?
46
+
18
47
  @descendant_counts[descendant_type.to_sym] = get_descendant_count(descendant_type) - by
19
48
  end
20
49
 
50
+ # Returns the descendant count for the given type
51
+ #
52
+ # @param descendant_type [String, Symbol] the descendent's type
53
+ # @return [Integer] the count
54
+ #
21
55
  def get_descendant_count(descendant_type)
22
56
  @descendant_counts[descendant_type.to_sym] || 0
23
57
  end
24
58
 
59
+ # Makes a new Ancestor around the same element, with new counts
60
+ #
25
61
  def clone
62
+ # @todo Delete later if not used
26
63
  Ancestor.new(element)
27
64
  end
28
65
 
@@ -1,17 +1,35 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kitchen
4
+ # A specialized form of +Document+ for our books.
5
+ #
2
6
  class BookDocument < Document
3
7
 
8
+ # This book's short name, used to look up translations, etc.
9
+ # @return [Symbol] the name
10
+ #
4
11
  attr_reader :short_name
5
12
 
13
+ # Creates a new BookDocument
14
+ #
15
+ # @param document [Document, Nokogiri::XML::Document] the underlying document;
16
+ # if a +Document+ it is converted to a +Nokogiri::XML::Document+
17
+ # @param short_name [Symbol, String] the book's short name
18
+ # @param config [Config] the book's configuration
19
+ #
6
20
  def initialize(document:, short_name: :not_set, config: nil)
7
- @short_name = short_name
21
+ @short_name = short_name.to_sym
8
22
 
9
23
  super(nokogiri_document: document.is_a?(Document) ? document.raw : document,
10
24
  config: config)
11
25
  end
12
26
 
27
+ # Returns the top-level +BookElement+ for this document
28
+ #
29
+ # @return [BookElement]
30
+ #
13
31
  def book
14
- BookElement.new(node: nokogiri_document.search("html").first, document: self)
32
+ BookElement.new(node: nokogiri_document.search('html').first, document: self)
15
33
  end
16
34
 
17
35
  end
@@ -1,6 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kitchen
4
+ # An element for an entire book
5
+ #
2
6
  class BookElement < ElementBase
3
7
 
8
+ # Creates a new +BookElement+
9
+ #
10
+ # @param node [Nokogiri::XML::Node] the node this element wraps
11
+ # @param document [Document] this element's document
12
+ #
4
13
  def initialize(node:, document: nil)
5
14
  super(node: node,
6
15
  document: document,
@@ -8,16 +17,28 @@ module Kitchen
8
17
  short_type: :book)
9
18
  end
10
19
 
20
+ # Returns the "body" element
21
+ #
22
+ # @return [Element]
23
+ #
11
24
  def body
12
- first!("body")
25
+ first!('body')
13
26
  end
14
27
 
28
+ # Returns the top metadata element
29
+ #
30
+ # @return [MetadataElement]
31
+ #
15
32
  def metadata
16
- first!("div[data-type='metadata']")
33
+ metadatas.first
17
34
  end
18
35
 
36
+ # Returns the table of contents (toc) element
37
+ #
38
+ # @return [Element]
39
+ #
19
40
  def toc
20
- first!("nav#toc")
41
+ first!('nav#toc')
21
42
  end
22
43
 
23
44
  end
@@ -1,4 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kitchen
4
+ # An enumerator for book elements
5
+ #
2
6
  class BookElementEnumerator < ElementEnumeratorBase
3
7
  # Unsure if this class is needed; there is only one book element per document
4
8
  end
@@ -1,17 +1,31 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kitchen
4
+ # A specialized +Recipe+ that yields a +BookDocument+ instead of a plain
5
+ # +Document+
6
+ #
2
7
  class BookRecipe < Recipe
3
8
 
9
+ # The book's short name
10
+ #
11
+ # @return [Symbol]
12
+ #
4
13
  attr_reader :book_short_name
5
14
 
6
15
  # Make a new BookRecipe
7
16
  #
17
+ # @param book_short_name [Symbol, String] the book's short name
8
18
  # @yieldparam doc [BookDocument] an object representing an XML document
9
19
  #
10
20
  def initialize(book_short_name: :not_set, &block)
11
- @book_short_name = book_short_name
21
+ @book_short_name = book_short_name.to_sym
12
22
  super(&block)
13
23
  end
14
24
 
25
+ # Overrides +document=+ to ensure a +BookDocument+ is stored
26
+ #
27
+ # @param document [Document, Nokogiri::XML::Document] the document
28
+ #
15
29
  def document=(document)
16
30
  super(document)
17
31
  @document = Kitchen::BookDocument.new(
@@ -1,6 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kitchen
4
+ # An element for a chapter
5
+ #
2
6
  class ChapterElement < ElementBase
3
7
 
8
+ # Creates a new +ChapterElement+
9
+ #
10
+ # @param node [Nokogiri::XML::Node] the node this element wraps
11
+ # @param document [Document] this element's document
12
+ #
4
13
  def initialize(node:, document: nil)
5
14
  super(node: node,
6
15
  document: document,
@@ -8,27 +17,58 @@ module Kitchen
8
17
  short_type: :chapter)
9
18
  end
10
19
 
20
+ # Returns the title element (the one in the immediate children, not the one in the metadata)
21
+ #
22
+ # @raise [ElementNotFoundError] if no matching element is found
23
+ # @return [Element]
24
+ #
11
25
  def title
12
26
  # Get the title in the immediate children, not the one in the metadata. Could use
13
- # CSS of ":not([data-type='metadata']) > [data-type='document-title'], [data-type='document-title']"
27
+ # CSS of ":not([data-type='metadata']) >
28
+ # [data-type='document-title'], [data-type='document-title']"
14
29
  # but xpath is shorter
15
30
  first!("./*[@data-type = 'document-title']")
16
31
  end
17
32
 
33
+ # Returns the introduction page
34
+ #
35
+ # @return [Element, nil]
36
+ #
18
37
  def introduction_page
19
38
  pages('.introduction').first
20
39
  end
21
40
 
41
+ # Returns an enumerator for the glossaries
42
+ #
43
+ # @return [ElementEnumerator]
44
+ #
22
45
  def glossaries
23
46
  search("div[data-type='glossary']")
24
47
  end
25
48
 
49
+ # Returns an enumerator for the key equations
50
+ #
51
+ # @return [ElementEnumerator]
52
+ #
26
53
  def key_equations
27
- search("section.key-equations")
54
+ search('section.key-equations')
55
+ end
56
+
57
+ # Returns an enumerator for the abstracts
58
+ #
59
+ # @return [ElementEnumerator]
60
+ #
61
+ def abstracts
62
+ search('[data-type="abstract"]')
28
63
  end
29
64
 
65
+ # Returns true if this class represents the element for the given node
66
+ #
67
+ # @param node [Nokogiri::XML::Node] the underlying node
68
+ # @return [Boolean]
69
+ #
30
70
  def self.is_the_element_class_for?(node)
31
- node['data-type'] == "chapter"
71
+ node['data-type'] == 'chapter'
32
72
  end
33
73
 
34
74
  end
@@ -1,9 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Kitchen
4
+ # An enumerator for chapter elements
5
+ #
2
6
  class ChapterElementEnumerator < ElementEnumeratorBase
3
7
 
8
+ # Returns a factory for this enumerator
9
+ #
10
+ # @return [ElementEnumeratorFactory]
11
+ #
4
12
  def self.factory
5
13
  ElementEnumeratorFactory.new(
6
- default_css_or_xpath: "div[data-type='chapter']", # TODO element.document.selectors.chapter
14
+ default_css_or_xpath: "div[data-type='chapter']", # TODO: element.document.selectors.chapter
7
15
  sub_element_class: ChapterElement,
8
16
  enumerator_class: self
9
17
  )