openstax_kitchen 1.0.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (182) 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 +2 -2
  6. data/.inch.yml +6 -0
  7. data/.rubocop.yml +65 -0
  8. data/CHANGELOG.md +85 -2
  9. data/Gemfile +5 -3
  10. data/Gemfile.lock +66 -18
  11. data/README.md +69 -15
  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 +15 -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 +40 -5
  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 -6
  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 +21 -6
  31. data/lib/kitchen/composite_page_element.rb +35 -7
  32. data/lib/kitchen/composite_page_element_enumerator.rb +9 -1
  33. data/lib/kitchen/config.rb +20 -6
  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/main.rb +18 -0
  39. data/lib/kitchen/directions/bake_chapter_glossary/v1.rb +30 -0
  40. data/lib/kitchen/directions/bake_chapter_introductions.rb +7 -7
  41. data/lib/kitchen/directions/bake_chapter_key_concepts/main.rb +16 -0
  42. data/lib/kitchen/directions/bake_chapter_key_concepts/v1.rb +35 -0
  43. data/lib/kitchen/directions/bake_chapter_key_equations.rb +30 -20
  44. data/lib/kitchen/directions/bake_chapter_section_exercises/main.rb +11 -0
  45. data/lib/kitchen/directions/bake_chapter_section_exercises/v1.rb +28 -0
  46. data/lib/kitchen/directions/bake_chapter_summary.rb +45 -36
  47. data/lib/kitchen/directions/bake_chapter_title/main.rb +11 -0
  48. data/lib/kitchen/directions/bake_chapter_title/v1.rb +24 -0
  49. data/lib/kitchen/directions/bake_checkpoint.rb +44 -0
  50. data/lib/kitchen/directions/bake_composite_chapters.rb +14 -0
  51. data/lib/kitchen/directions/bake_composite_pages.rb +2 -2
  52. data/lib/kitchen/directions/bake_equations.rb +37 -0
  53. data/lib/kitchen/directions/bake_example.rb +39 -11
  54. data/lib/kitchen/directions/bake_figure.rb +8 -5
  55. data/lib/kitchen/directions/bake_first_elements.rb +16 -0
  56. data/lib/kitchen/directions/bake_footnotes/main.rb +2 -2
  57. data/lib/kitchen/directions/bake_footnotes/v1.rb +6 -5
  58. data/lib/kitchen/directions/bake_free_response/free_response.xhtml.erb +10 -0
  59. data/lib/kitchen/directions/bake_free_response/main.rb +11 -0
  60. data/lib/kitchen/directions/bake_free_response/v1.rb +29 -0
  61. data/lib/kitchen/directions/bake_further_research.rb +59 -0
  62. data/lib/kitchen/directions/bake_index/main.rb +2 -2
  63. data/lib/kitchen/directions/bake_index/v1.rb +46 -18
  64. data/lib/kitchen/directions/bake_link_placeholders.rb +24 -0
  65. data/lib/kitchen/directions/bake_math_in_paragraph.rb +5 -3
  66. data/lib/kitchen/directions/bake_non_introduction_pages.rb +26 -0
  67. data/lib/kitchen/directions/bake_notes/bake_autotitled_notes.rb +29 -0
  68. data/lib/kitchen/directions/bake_notes/bake_note_subtitle.rb +22 -0
  69. data/lib/kitchen/directions/bake_notes/bake_numbered_notes.rb +51 -0
  70. data/lib/kitchen/directions/bake_notes/bake_unclassified_notes.rb +30 -0
  71. data/lib/kitchen/directions/bake_numbered_exercise/main.rb +15 -0
  72. data/lib/kitchen/directions/bake_numbered_exercise/v1.rb +47 -0
  73. data/lib/kitchen/directions/bake_numbered_table/main.rb +4 -4
  74. data/lib/kitchen/directions/bake_numbered_table/v1.rb +37 -18
  75. data/lib/kitchen/directions/bake_page_abstracts.rb +30 -0
  76. data/lib/kitchen/directions/bake_preface/main.rb +11 -0
  77. data/lib/kitchen/directions/bake_preface/v1.rb +18 -0
  78. data/lib/kitchen/directions/bake_references/main.rb +16 -0
  79. data/lib/kitchen/directions/bake_references/v1.rb +48 -0
  80. data/lib/kitchen/directions/bake_stepwise.rb +8 -12
  81. data/lib/kitchen/directions/bake_suggested_reading.rb +31 -0
  82. data/lib/kitchen/directions/bake_theorem/main.rb +11 -0
  83. data/lib/kitchen/directions/bake_theorem/v1.rb +28 -0
  84. data/lib/kitchen/directions/bake_toc.rb +49 -22
  85. data/lib/kitchen/directions/bake_unit_title/main.rb +11 -0
  86. data/lib/kitchen/directions/bake_unit_title/v1.rb +23 -0
  87. data/lib/kitchen/directions/bake_unnumbered_tables.rb +7 -5
  88. data/lib/kitchen/directions/book_answer_key_container/eob_solutions_container.xhtml.erb +9 -0
  89. data/lib/kitchen/directions/book_answer_key_container/main.rb +11 -0
  90. data/lib/kitchen/directions/book_answer_key_container/v1.rb +13 -0
  91. data/lib/kitchen/directions/chapter_review_container/chapter_review.xhtml.erb +9 -0
  92. data/lib/kitchen/directions/chapter_review_container/main.rb +11 -0
  93. data/lib/kitchen/directions/chapter_review_container/v1.rb +13 -0
  94. data/lib/kitchen/directions/eoc_section_title_link_snippet.rb +20 -0
  95. data/lib/kitchen/directions/move_exercises_to_eoc/main.rb +27 -0
  96. data/lib/kitchen/directions/move_exercises_to_eoc/v1.rb +36 -0
  97. data/lib/kitchen/directions/move_exercises_to_eoc/v2.rb +49 -0
  98. data/lib/kitchen/directions/move_solutions_to_answer_key/main.rb +14 -0
  99. data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/american_government.rb +19 -0
  100. data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/calculus.rb +41 -0
  101. data/lib/kitchen/directions/move_solutions_to_answer_key/strategies/uphysics.rb +63 -0
  102. data/lib/kitchen/directions/move_solutions_to_answer_key/v1.rb +34 -0
  103. data/lib/kitchen/directions/move_title_text_into_span.rb +2 -2
  104. data/lib/kitchen/document.rb +83 -13
  105. data/lib/kitchen/element.rb +20 -3
  106. data/lib/kitchen/element_base.rb +373 -63
  107. data/lib/kitchen/element_enumerator.rb +8 -0
  108. data/lib/kitchen/element_enumerator_base.rb +297 -28
  109. data/lib/kitchen/element_enumerator_factory.rb +64 -53
  110. data/lib/kitchen/element_factory.rb +27 -12
  111. data/lib/kitchen/errors.rb +5 -0
  112. data/lib/kitchen/example_element.rb +21 -6
  113. data/lib/kitchen/example_element_enumerator.rb +9 -1
  114. data/lib/kitchen/exercise_element.rb +42 -0
  115. data/lib/kitchen/exercise_element_enumerator.rb +21 -0
  116. data/lib/kitchen/figure_element.rb +36 -5
  117. data/lib/kitchen/figure_element_enumerator.rb +9 -1
  118. data/lib/kitchen/metadata_element.rb +34 -0
  119. data/lib/kitchen/metadata_element_enumerator.rb +21 -0
  120. data/lib/kitchen/mixins/block_error_if.rb +24 -4
  121. data/lib/kitchen/note_element.rb +48 -20
  122. data/lib/kitchen/note_element_enumerator.rb +9 -1
  123. data/lib/kitchen/oven.rb +66 -15
  124. data/lib/kitchen/page_element.rb +84 -14
  125. data/lib/kitchen/page_element_enumerator.rb +9 -1
  126. data/lib/kitchen/pantry.rb +28 -1
  127. data/lib/kitchen/patches/nokogiri.rb +19 -2
  128. data/lib/kitchen/patches/renderable.rb +9 -3
  129. data/lib/kitchen/patches/string.rb +8 -0
  130. data/lib/kitchen/recipe.rb +69 -32
  131. data/lib/kitchen/reference_element.rb +27 -0
  132. data/lib/kitchen/references_element_enumerator.rb +20 -0
  133. data/lib/kitchen/search_history.rb +43 -4
  134. data/lib/kitchen/search_query.rb +106 -0
  135. data/lib/kitchen/selector.rb +24 -0
  136. data/lib/kitchen/selectors/base.rb +65 -0
  137. data/lib/kitchen/selectors/standard_1.rb +21 -0
  138. data/lib/kitchen/table_element.rb +55 -7
  139. data/lib/kitchen/table_element_enumerator.rb +9 -1
  140. data/lib/kitchen/templates/eob_section_title_template.xhtml.erb +10 -0
  141. data/lib/kitchen/templates/eoc_section_title_template.xhtml.erb +10 -0
  142. data/lib/kitchen/term_element.rb +15 -4
  143. data/lib/kitchen/term_element_enumerator.rb +9 -1
  144. data/lib/kitchen/transliterations.rb +7 -5
  145. data/lib/kitchen/type_casting_element_enumerator.rb +17 -1
  146. data/lib/kitchen/unit_element.rb +45 -0
  147. data/lib/kitchen/unit_element_enumerator.rb +20 -0
  148. data/lib/kitchen/utils.rb +10 -13
  149. data/lib/kitchen/version.rb +5 -1
  150. data/lib/locales/en.yml +18 -7
  151. data/lib/locales/pl.yml +24 -0
  152. data/lib/openstax_kitchen.rb +59 -0
  153. data/openstax_kitchen.gemspec +26 -20
  154. data/tutorials/00/solution1.rb +9 -0
  155. data/tutorials/00/solution2.rb +8 -0
  156. data/tutorials/01/solution1.rb +18 -0
  157. data/tutorials/01/solution2.rb +26 -0
  158. data/tutorials/02/solution1.rb +31 -0
  159. data/tutorials/03/{solution_1.rb → solution1.rb} +6 -4
  160. data/tutorials/03/solution2.rb +18 -0
  161. data/tutorials/04/{solution_1.rb → solution1.rb} +4 -2
  162. data/tutorials/04/{solution_2.rb → solution2.rb} +6 -4
  163. data/tutorials/05/solution1.rb +11 -0
  164. data/tutorials/check_it +16 -15
  165. data/tutorials/setup_my_recipes +7 -6
  166. metadata +148 -27
  167. data/Dockerfile +0 -19
  168. data/bin/normalize +0 -79
  169. data/books/chemistry2e/bake.rb +0 -133
  170. data/docker-compose.yml +0 -12
  171. data/docker/entrypoint +0 -9
  172. data/lib/kitchen.rb +0 -57
  173. data/lib/kitchen/directions/bake_chapter_glossary.rb +0 -34
  174. data/lib/kitchen/directions/bake_exercises.rb +0 -164
  175. data/lib/kitchen/directions/bake_notes.rb +0 -58
  176. data/tutorials/00/solution_1.rb +0 -7
  177. data/tutorials/00/solution_2.rb +0 -6
  178. data/tutorials/01/solution_1.rb +0 -16
  179. data/tutorials/01/solution_2.rb +0 -24
  180. data/tutorials/02/solution_1.rb +0 -29
  181. data/tutorials/03/solution_2.rb +0 -15
  182. data/tutorials/05/solution_1.rb +0 -9
data/README.md CHANGED
@@ -3,14 +3,16 @@
3
3
  [![Tests](https://github.com/openstax/kitchen/workflows/Tests/badge.svg)](https://github.com/openstax/kitchen/actions?query=workflow:Tests)
4
4
  [![Coverage Status](https://img.shields.io/codecov/c/github/openstax/kitchen.svg)](https://codecov.io/gh/openstax/kitchen)
5
5
 
6
- Kitchen lets you modify the structure and content of XML files. You create a `Recipe` with instructions and `bake` it in the `Oven`
6
+ Kitchen lets you modify the structure and content of XML files. You create a `Recipe` with instructions and `bake` it in the `Oven`.
7
+
8
+ [Full documentation at rubydoc.info](https://rubydoc.info/github/openstax/kitchen).
7
9
 
8
10
  ## Installation
9
11
 
10
12
  Add this line to your application's Gemfile:
11
13
 
12
14
  ```ruby
13
- gem 'kitchen'
15
+ gem 'openstax_kitchen'
14
16
  ```
15
17
 
16
18
  And then execute:
@@ -19,7 +21,7 @@ And then execute:
19
21
 
20
22
  Or install it yourself as:
21
23
 
22
- $ gem install kitchen
24
+ $ gem install openstax_kitchen
23
25
 
24
26
  ## Two Ways to Use Kitchen
25
27
 
@@ -32,7 +34,7 @@ We'll first talk about the generic way since those tools are also available in t
32
34
  Kitchen lets you modify the structure and content of XML files. You create a `Recipe` and `bake` it in the `Oven`:
33
35
 
34
36
  ```ruby
35
- require "kitchen"
37
+ require "openstax_kitchen"
36
38
 
37
39
  recipe = Kitchen::Recipe.new do |document|
38
40
  document.search("div.section").each do |element|
@@ -208,6 +210,13 @@ And we can wrap an element with another element:
208
210
  doc.search("span").first.wrap("<span class='other'>")
209
211
  ```
210
212
 
213
+ or wrap an element's children:
214
+
215
+ ```ruby
216
+ # <div><span>Hi</span></div> => <div><span><span class="other" data-type="foo">Hi</span></span></div>
217
+ doc.search("span").first.wrap_children('span', class: 'other', data_type: 'foo')
218
+ ```
219
+
211
220
  ### Checking for elements
212
221
 
213
222
  You can see if an element contains an element matching a selector:
@@ -271,6 +280,31 @@ The CSS for these specific search methods is hidden away so you don't have to de
271
280
  doc.book.tables("$.unnumbered").cut
272
281
  ```
273
282
 
283
+ Sometimes, it is difficult to setup a search using CSS. In such cases, you can also pass `only` and `except` arguments to search methods, e.g.:
284
+
285
+ ```ruby
286
+ doc.book.figures(except: :subfigure?)
287
+ ```
288
+
289
+ `only` and `except` can be the names of methods (that return truthy/falsy values) on the element being iterated over, as shown above, or they can be lambdas or procs as shown here:
290
+
291
+ ```ruby
292
+ doc.book.figures(only: ->(fig) { fig.children.count == 2 })
293
+ ```
294
+
295
+ Obviously this is a somewhat contrived example, but the idea is that by passing a callable you can do complex searches.
296
+
297
+ ### Overriding Default Book-Oriented Selectors
298
+
299
+ Book-oriented methods like `book.pages.figures` hide from us the CSS or XPath selectors that let us find child elements like `.pages`. But sometimes, the default selector we have isn't what is used in a certain book. In these cases, we can override the selector once in the recipe and still continue to use the book-oriented usage. For example, a page summary is normally found using the CSS `section.summary`. But some books use a `.section-summary` class. For these books, we can override the selectors in their recipes:
300
+
301
+ ```ruby
302
+ recipe = Kitchen::BookRecipe.new do |doc|
303
+ doc.selectors.override(
304
+ page_summary: ".section-summary"
305
+ )
306
+ ```
307
+
274
308
  ## Directions
275
309
 
276
310
  All of the above talks about the how to search through the XML file and perform basic operations on that file. Our recipes will be combinations of all of the above: search for elements; cut, copy and paste them; count them; rework them; etc.
@@ -430,10 +464,10 @@ Want to make a one-file script to do some baking? Use the "inline" form of bund
430
464
  require "bundler/inline"
431
465
 
432
466
  gemfile do
433
- gem 'kitchen', git: 'https://github.com/openstax/kitchen.git', ref: 'some_sha_here'
467
+ gem 'openstax_kitchen', '2.0.0'
434
468
  end
435
469
 
436
- require "kitchen"
470
+ require "openstax_kitchen"
437
471
 
438
472
  recipe = Kitchen::Recipe.new do |doc|
439
473
  # ... recipe steps here
@@ -452,19 +486,23 @@ Incidentally, the `bake` method returns timing information, if you `puts` its re
452
486
 
453
487
  ### Docker
454
488
 
455
- You can use Docker for your development environment.
489
+ You can use Docker for your development environment. To build the image:
456
490
 
457
491
  ```bash
458
- $> docker-compose up -d
492
+ $> ./docker/build
459
493
  ```
460
494
 
461
- to build and run the Docker container, then:
495
+ To drop into the running container:
462
496
 
463
497
  ```bash
464
498
  $> ./docker/bash
465
499
  ```
466
500
 
467
- To drop into the container at the command line.
501
+ To run specs (or something else) from the host:
502
+
503
+ ```bash
504
+ $> ./docker/run rspec
505
+ ```
468
506
 
469
507
  ### Non-Docker
470
508
 
@@ -583,6 +621,8 @@ Run `yard server --reload` to watch for changes in your local codebase everytime
583
621
 
584
622
  Navidate to `http://localhost:8808/` to view documentation in your browser.
585
623
 
624
+ Use the `inch` gem to get feedback on where documentation is lacking `bundle exec inch` (add `--help` for more options).
625
+
586
626
  ### Specs
587
627
 
588
628
  Run `bundle exec rspec` to run the specs. `rake rspec` probably does the same thing.
@@ -609,7 +649,25 @@ expect(book_1).to match_html_nodes("some string of HTML here")
609
649
  4. Click "Remote-Containers: Open Folder in Container"
610
650
  5. Select the cloned kitchen folder.
611
651
 
612
- This (assuming you have Docker installed) will launch a docker container for Kitchen, install Ruby and needed libraries, and then let you edit the code running in that container through VSCode. Solargraph will work (code completion and inline documentation).
652
+ This (assuming you have Docker installed) will launch a docker container for Kitchen, install Ruby and needed libraries, and then let you edit the code running in that container through VSCode. Solargraph will work (code completion and inline documentation) as will Rubocop for linting.
653
+
654
+ ### Rubocop
655
+
656
+ Rubocop is good for helping us keep our code style standardized, but it isn't the end-all be-all of things. We can disable certain checks within a file, e.g.
657
+
658
+ ```ruby
659
+ # rubocop:disable Style/NumericPredicate
660
+ ```
661
+
662
+ or we can disable or change global settings in the `.rubocop.yml` file.
663
+
664
+ Rubocop is setup to run within the VSCode dev container (see above).
665
+
666
+ The [lefthook](https://github.com/Arkweid/lefthook) is included in the Docker build. When you push your code to GitHub, lefthook runs Rubocop on all the files you have changed. It won't let you push if you have Rubocop errors. You'll have to fix the errors or make changes to the `.rubocop.yml` files to bypass the errors. You can also run lefthook directly with
667
+
668
+ ```bash
669
+ $ /code> lefthook run pre-push
670
+ ```
613
671
 
614
672
  #### Misc References
615
673
 
@@ -643,13 +701,9 @@ The gem is available as open source under the terms of the [MIT License](https:/
643
701
  ## TODO
644
702
 
645
703
  * Specs galore :-)
646
- * `$` search path substitution (making sure not to mess up xpath)
647
704
  * Think up and handle a bunch more recipe errors, test they all raise some kind of `RecipeError`.
648
705
  * Encapsulate numbering schemes (e.g. chapter pages are "5.2", appendix pages are "D7") and maybe set on book document? Right now we are doing inline things like `*('A'..'Z')][page.count_in(:book)-1]}#{table.count_in(:page)` which is ugly.
649
- * Add rubocop for linting.
650
706
  * Control I18n language in Oven.
651
- * Get doc normalization scripts into this repo from testkitchen (for comparing two large baked outputs).
652
- * Change from ElementBase <- Element to Element <- BasicElement
653
707
  * README: element_children, .only, selectors, config files
654
708
  * Use ERB for more readable string building?
655
709
 
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 "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 "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,15 @@
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
+ -w /code \
14
+ openstax/kitchen.ci:latest \
15
+ /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,24 +1,59 @@
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,
7
- enumerator_class: BookElementEnumerator,
8
- short_type: :book)
16
+ enumerator_class: BookElementEnumerator)
17
+ end
18
+
19
+ # Returns the short type
20
+ # @return [Symbol]
21
+ #
22
+ def self.short_type
23
+ :book
9
24
  end
10
25
 
26
+ # Returns the "body" element
27
+ #
28
+ # @return [Element]
29
+ #
11
30
  def body
12
- first!("body")
31
+ first!('body')
13
32
  end
14
33
 
34
+ # Returns the top metadata element
35
+ #
36
+ # @return [MetadataElement]
37
+ #
15
38
  def metadata
16
- first!("div[data-type='metadata']")
39
+ metadatas.first
17
40
  end
18
41
 
42
+ # Returns the table of contents (toc) element
43
+ #
44
+ # @return [Element]
45
+ #
19
46
  def toc
20
- first!("nav#toc")
47
+ first!('nav#toc')
21
48
  end
22
49
 
50
+ # Returns true if this class represents the element for the given node
51
+ #
52
+ # @param node [Nokogiri::XML::Node] the underlying node
53
+ # @return [Boolean]
54
+ #
55
+ def self.is_the_element_class_for?(node, **)
56
+ node.name == 'body'
57
+ end
23
58
  end
24
59
  end