coursegen 0.8.1 → 0.9.3

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.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/pr.yml +19 -0
  3. data/.gitignore +3 -0
  4. data/Gemfile.lock +80 -57
  5. data/README.md +285 -69
  6. data/Rakefile +10 -1
  7. data/coursegen.gemspec +26 -26
  8. data/lib/coursegen.rb +5 -2
  9. data/lib/coursegen/cli.rb +49 -14
  10. data/lib/coursegen/course/data/citem.rb +10 -1
  11. data/lib/coursegen/course/data/data_adaptor.rb +16 -6
  12. data/lib/coursegen/course/data/section.rb +1 -1
  13. data/lib/coursegen/course/helpers/bootstrap_markup.rb +15 -15
  14. data/lib/coursegen/course/helpers/content_helpers.rb +158 -94
  15. data/lib/coursegen/course/helpers/formatting_helpers.rb +6 -10
  16. data/lib/coursegen/course/helpers/ical_feed_helpers.rb +2 -1
  17. data/lib/coursegen/course/helpers/lecture_helpers.rb +3 -2
  18. data/lib/coursegen/course/helpers/list_of.rb +40 -20
  19. data/lib/coursegen/course/helpers/list_of_helpers.rb +20 -14
  20. data/lib/coursegen/course/helpers/logging_helpers.rb +13 -12
  21. data/lib/coursegen/course/helpers/navigation_helpers.rb +62 -23
  22. data/lib/coursegen/course/helpers/sidebar_helpers.rb +19 -18
  23. data/lib/coursegen/course/helpers/table_helpers.rb +5 -4
  24. data/lib/coursegen/course/schedule/scheduler.rb +52 -19
  25. data/lib/coursegen/templates.rb +30 -23
  26. data/lib/coursegen/version.rb +3 -1
  27. data/spec/lectures_spec.rb +60 -50
  28. data/spec/play_spec.rb +24 -12
  29. data/spec/scheduler_spec.rb +87 -27
  30. data/tech_debt.md +5 -0
  31. data/templates/Rules +14 -19
  32. data/templates/cg_config.rb +105 -21
  33. data/templates/content/bootstrap/css/custom.css +87 -151
  34. data/templates/content/bootstrap/css/full-width-pics.css +8 -64
  35. data/templates/content/bootstrap/css/postit.css +7 -0
  36. data/templates/content/bootstrap/css/toasty.css +3 -0
  37. data/templates/content/content/index.md.erb +1 -1
  38. data/templates/content/content/intro/course_toc.md.erb +0 -1
  39. data/templates/content/content/intro/welcome.md.erb +1 -3
  40. data/templates/content/content/lectures/part1/02_here_we_go.md.erb +22 -1
  41. data/templates/content/content/lectures/part2/01_start_part2.md.erb +2 -1
  42. data/templates/content/content/lectures/part2/02_continue_part2.md.erb +3 -2
  43. data/templates/layouts/banner.html.erb +4 -4
  44. data/templates/layouts/body_footer.html +3 -4
  45. data/templates/layouts/body_header.html.erb +25 -7
  46. data/templates/layouts/bottom_includes.html.erb +21 -10
  47. data/templates/layouts/course.html.erb +7 -21
  48. data/templates/layouts/helpful_box.html +1 -1
  49. data/templates/layouts/nav-menus.html.erb +16 -36
  50. data/templates/layouts/sidebar.html.erb +9 -8
  51. data/templates/layouts/slides.html.erb +69 -0
  52. data/templates/layouts/top_includes.html.erb +24 -23
  53. metadata +36 -28
  54. data/.DS_Store +0 -0
  55. data/.vscode/settings.json +0 -2
  56. data/templates/.DS_Store +0 -0
  57. data/templates/Guardfile +0 -9
  58. data/templates/content/bootstrap/css/tipuesearch.css +0 -163
  59. data/templates/content/bootstrap/js/tipuesearch.js +0 -379
  60. data/templates/content/bootstrap/js/tipuesearch.min.js +0 -12
  61. data/templates/content/bootstrap/js/tipuesearch_content.js +0 -13
  62. data/templates/content/bootstrap/js/tipuesearch_set.js +0 -23
  63. data/templates/layouts/main_navbar.html.erb +0 -21
data/Rakefile CHANGED
@@ -1 +1,10 @@
1
- require "bundler/gem_tasks"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec'
5
+
6
+ begin
7
+ require 'rspec/core/rake_task'
8
+ RSpec::Core::RakeTask.new(:spec)
9
+ rescue LoadError
10
+ end
@@ -1,37 +1,37 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
1
+ lib = File.expand_path('lib', __dir__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
3
  require 'coursegen/version'
5
4
 
6
5
  Gem::Specification.new do |spec|
7
- spec.name = "coursegen"
6
+ spec.name = 'coursegen'
8
7
  spec.version = Coursegen::VERSION
9
- spec.authors = ["Pito Salas"]
10
- spec.email = ["pitosalas@gmail.com"]
11
- spec.summary = "Use Nanoc to build courses and deploy them to S3"
12
- spec.description = "Use Nanoc to build courses and deploy them to S3"
13
- spec.homepage = ""
14
- spec.license = "MIT"
8
+ spec.authors = ['Pito Salas']
9
+ spec.email = ['pitosalas@gmail.com']
10
+ spec.summary = 'Use Nanoc to build courses and deploy them to S3'
11
+ spec.description = 'Use Nanoc to build courses and deploy them to S3'
12
+ spec.homepage = ''
13
+ spec.license = 'MIT'
15
14
 
16
15
  spec.files = `git ls-files -z`.split("\x0")
17
16
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
17
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
- spec.require_paths = ["lib"]
18
+ spec.require_paths = ['lib']
20
19
 
21
- spec.add_development_dependency "bundler"
22
- spec.add_development_dependency "rake"
23
-
24
- spec.add_dependency "nanoc"
25
- spec.add_dependency "thor"
26
- spec.add_dependency "rubytree"
27
- spec.add_dependency "cri"
28
- spec.add_dependency "nokogiri"
29
- spec.add_dependency "activesupport"
30
- spec.add_dependency "kramdown"
31
- spec.add_dependency "adsf"
32
- spec.add_dependency "guard"
33
- spec.add_dependency "guard-shell"
34
- spec.add_dependency "tzinfo"
35
- spec.add_dependency "icalendar"
36
- spec.add_dependency "byebug"
20
+ spec.add_development_dependency 'bundler'
21
+ spec.add_development_dependency 'rake'
22
+ spec.add_development_dependency 'rspec'
23
+
24
+ spec.add_dependency 'activesupport'
25
+ spec.add_dependency 'adsf'
26
+ spec.add_dependency 'byebug'
27
+ spec.add_dependency 'cri'
28
+ spec.add_dependency 'guard'
29
+ spec.add_dependency 'guard-shell'
30
+ spec.add_dependency 'icalendar'
31
+ spec.add_dependency 'kramdown'
32
+ spec.add_dependency 'nanoc'
33
+ spec.add_dependency 'nokogiri'
34
+ spec.add_dependency 'rubytree'
35
+ spec.add_dependency 'thor'
36
+ spec.add_dependency 'tzinfo'
37
37
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'nokogiri'
2
4
 
3
5
  require 'coursegen/version'
@@ -25,7 +27,8 @@ require 'coursegen/course/helpers/list_of'
25
27
  require 'coursegen/course/helpers/ical_feed_helpers'
26
28
  require 'coursegen/course/lib/helpers_'
27
29
 
28
-
30
+ # Coursegen is a course curriculum site generator based on nanoc, with
31
+ # support for sections, lectures, code examples, homeworks, course
32
+ # calendar and lots more.
29
33
  module Coursegen
30
- # Your code goes here...
31
34
  end
@@ -1,46 +1,81 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'thor'
2
4
  require 'coursegen/templates'
3
5
  require 'nanoc'
4
6
  require './cg_config.rb' if File.exist? 'cg_config.rb'
5
7
 
6
8
  module CourseGen
9
+ # Class CLI provides a command line utility for creating, building, and
10
+ # deploying a Coursegen site.
7
11
  class CLI < Thor
8
12
  include Thor::Actions
9
13
 
10
- desc "new COURSE", "Create a new course by calling nanoc. Argument is name of the COURSE"
14
+ # New creates a new nanoc site.
15
+ #
16
+ # By default, the new site does not contain any course template.
17
+ # To generate a course template within the newly created nanoc site,
18
+ # run: `cg prepare`.
19
+ #
20
+ # See: https://nanoc.ws/doc/reference/commands/#create-site
21
+ desc 'new COURSE',
22
+ 'Create a new course by calling nanoc. Argument is name of the COURSE'
11
23
  def new(course)
12
24
  run("nanoc create-site #{course}")
13
25
  end
14
26
 
15
- desc "prepare", "Update with the latest coursegen code and templates."
27
+ # Prepare generates a new course template within a nanoc site.
28
+ desc 'prepare',
29
+ 'Update with the latest coursegen code and templates.'
16
30
  def prepare
17
31
  check_valid_directory
18
32
  tplt = CourseGen::Templates.new
19
33
  tplt.generate_all
20
34
  end
21
35
 
22
- desc "compile", "build the course and put resultant site into output directory"
36
+ # Compile builds the course site and outputs it to a local directory.
37
+ #
38
+ # By default, it outputs the course site to ./output.
39
+ #
40
+ # See: https://nanoc.ws/doc/reference/commands/#compile
41
+ desc 'compile',
42
+ 'build the course and put resultant site into output directory'
23
43
  def compile
24
- run("nanoc compile")
44
+ run 'nanoc compile'
25
45
  end
26
46
 
27
- desc "serve", "start local web server to test the course web site"
47
+ # Serve starts a static web server that serves the course site.
48
+ #
49
+ # By default, the web server serves from ./output.
50
+ #
51
+ # See: https://nanoc.ws/doc/reference/commands/#view
52
+ desc 'serve',
53
+ 'start local web server to test the course web site'
28
54
  def serve
29
- run("nanoc view")
55
+ run 'nanoc view'
30
56
  end
31
57
 
32
- desc "reset", "reset all generated content to bring the course back to a base state."
58
+ # Reset removes all generated contents.
59
+ desc 'reset',
60
+ 'reset all generated content to bring the course back to a base state.'
33
61
  def reset
34
- run "rm -frd tmp"
35
- run "rm -frd output"
62
+ run 'rm -frd tmp'
63
+ run 'rm -frd output'
36
64
  end
37
65
 
38
- desc "view", "view course site locally in browser"
66
+ # View opens an browser to the running course site.
67
+ desc 'view',
68
+ 'view course site locally in browser'
39
69
  def view
40
- run "open http://0.0.0.0:3000"
70
+ run 'open http://0.0.0.0:3000'
41
71
  end
42
72
 
43
- desc "deploy", "Deploy course to S3"
73
+ # Deploy deploys the course site to AWS S3.
74
+ #
75
+ # Note: `s3cmd` needs to be properly setup before this can work. Refer
76
+ # to README.md for detailed instructions.
77
+ desc 'deploy',
78
+ 'Deploy course to S3'
44
79
  def deploy
45
80
  run "s3cmd sync --delete-removed output/ s3://#{AWS_BUCKET}/"
46
81
  end
@@ -48,9 +83,9 @@ module CourseGen
48
83
  no_commands do
49
84
  def check_valid_directory
50
85
  if CourseGen::Templates.new.valid_cg_directory?
51
- say("Valid cg directory")
86
+ say 'Valid cg directory'
52
87
  else
53
- error("Invalid cg directory")
88
+ error 'Invalid cg directory'
54
89
  end
55
90
  end
56
91
  end
@@ -6,7 +6,8 @@ require 'active_support/inflector'
6
6
  #
7
7
  class CItem
8
8
  attr_reader :order, :section, :subsection, :subsection_citem, :title,
9
- :type, :identifier, :short_name, :status, :nitem, :css_class, :homework, :desc, :cat, :assigned
9
+ :type, :identifier, :short_name, :status, :nitem, :css_class,
10
+ :homework, :hwref, :desc, :cat, :assigned, :slides, :lectref, :reading, :due
10
11
  attr_accessor :lecture_number, :lecture_date, :start_time, :end_time
11
12
 
12
13
  # Callable with nitem=nil to create a mock
@@ -53,6 +54,7 @@ class CItem
53
54
 
54
55
  def schedule_start_date_time
55
56
  return if @lecture_date.nil?
57
+
56
58
  # schedule = Toc.instance.section(@section).schedule
57
59
  # lecture_date + schedule.start_time
58
60
  lecture_date + @start_time
@@ -60,6 +62,7 @@ class CItem
60
62
 
61
63
  def schedule_end_date_time
62
64
  return if @lecture_date.nil?
65
+
63
66
  # schedule = Toc.instance.section(@section).schedule
64
67
  # lecture_date + schedule.end_time
65
68
  lecture_date + @end_time
@@ -85,7 +88,13 @@ class CItem
85
88
  @homework = @nitem[:homework]
86
89
  @desc = @nitem[:desc]
87
90
  @cat = @nitem[:cat]
91
+ @hwref = @nitem[:hwref]
88
92
  @assigned = @nitem[:assigned]
93
+ @slides = @nitem[:slides]
94
+ @lectref = @nitem[:lectref]
95
+ @reading = @nitem[:reading]
96
+ @due = @nitem[:due]
97
+
89
98
  end
90
99
 
91
100
  def parse_identifier(ident)
@@ -5,8 +5,8 @@ class DataAdaptor
5
5
  end
6
6
 
7
7
  # column_selector is one of: :number, :date, :title, :homework
8
- COL_NAMES = {number: "#", date: "lecture date", title: "title",
9
- homework: "homework", desc: "description", cat: "category"}
8
+ COL_NAMES = { number: '#', date: 'lecture date', title: 'title',
9
+ homework: 'homework', desc: 'description', cat: 'category', hwref: 'homework', lectref: 'topics', reading: 'reading' }
10
10
 
11
11
  def column_name(column_selector)
12
12
  COL_NAMES[column_selector]
@@ -30,6 +30,8 @@ class DataAdaptor
30
30
  citem.identifier
31
31
  when :desc
32
32
  citem.desc
33
+ when :due
34
+ citem.due
33
35
  when :homework
34
36
  citem.homework
35
37
  when :assigned
@@ -39,13 +41,21 @@ class DataAdaptor
39
41
  when :end_date_time
40
42
  citem.schedule_end_date_time
41
43
  when :full_desc
42
- desc = citem.desc || ""
43
- hw = citem.homework || ""
44
- desc + ". HW: " + hw
44
+ desc = citem.desc || ''
45
+ hw = citem.homework || ''
46
+ desc + '. HW: ' + hw
45
47
  when :cat
46
48
  citem.cat
49
+ when :lectref
50
+ citem.lectref
51
+ when :hwref
52
+ citem.hwref
53
+ when :reading
54
+ citem.reading
55
+ when :order
56
+ citem.order
47
57
  else
48
- "error!"
58
+ 'error!'
49
59
  end
50
60
  end
51
61
  end
@@ -60,7 +60,7 @@ class Section
60
60
  def lookup_citem_by_identifier identifier
61
61
  res = @citems.select { |i| i.identifier.to_s == identifier }
62
62
  fail "TOC#lookup_citem_by_identifier failed to find: '#{identifier}'" if res.length != 1
63
- # binding.pry if res.length != 1
63
+ byebug if res.length != 1
64
64
  res[0]
65
65
  end
66
66
 
@@ -1,32 +1,32 @@
1
+ # Class BootstrapMarkup provides methods for using Bootstrap specific HTML
2
+ # markups.
1
3
  class BootstrapMarkup
2
4
  def initialize
3
- @str = ""
5
+ @str = ''
4
6
  end
5
7
 
6
- def table_begin(css_class = "table-condensed")
7
- puts css_class.class
8
+ def table_begin(css_class = 'table-condensed')
8
9
  @str << "<table class=\"table x #{css_class}\">"
9
- puts @str
10
10
  end
11
11
 
12
12
  def table_end
13
- @str << "</table>"
13
+ @str << '</table>'
14
14
  end
15
15
 
16
16
  def headers_begin
17
- @str << "<thead><tr>"
17
+ @str << '<thead><tr>'
18
18
  end
19
19
 
20
20
  def headers_end
21
- @str << "</tr></thead>"
21
+ @str << '</tr></thead>'
22
22
  end
23
23
 
24
24
  def header_begin
25
- @str << "<th>"
25
+ @str << '<th>'
26
26
  end
27
27
 
28
28
  def header_end
29
- @str << "</th>"
29
+ @str << '</th>'
30
30
  end
31
31
 
32
32
  def header_content(str)
@@ -34,27 +34,27 @@ class BootstrapMarkup
34
34
  end
35
35
 
36
36
  def row_begin
37
- @str << "<tr>"
37
+ @str << '<tr>'
38
38
  end
39
39
 
40
40
  def row_end
41
- @str << "</tr>"
41
+ @str << '</tr>'
42
42
  end
43
43
 
44
44
  def cell_begin
45
- @str << "<td>"
45
+ @str << '<td>'
46
46
  end
47
47
 
48
48
  def cell_end
49
- @str << "</td>"
49
+ @str << '</td>'
50
50
  end
51
51
 
52
52
  def bigcell_begin
53
- @str << "<td colspan=\"3\"><h5>"
53
+ @str << '<td colspan="3"><h5>'
54
54
  end
55
55
 
56
56
  def bigcell_end
57
- @str << "</h5></td>"
57
+ @str << '</h5></td>'
58
58
  end
59
59
 
60
60
  def cell_content(str)
@@ -1,23 +1,22 @@
1
- # Helpers to be used to annotate content
2
- require 'byebug'
1
+ # ContentHelpers is used to annotate content.
3
2
  module ContentHelpers
4
3
  def include_topic(item_symbol)
5
- incorporated_topic = lookup_nitem("topics", item_symbol.to_s)
4
+ incorporated_topic = lookup_nitem('topics', item_symbol.to_s)
6
5
  items[incorporated_topic.identifier.to_s].compiled_content
7
6
  end
8
7
 
9
8
  def include_page(item_symbol)
10
- incorporated_topic = lookup_nitem("pages", item_symbol.to_s)
9
+ incorporated_topic = lookup_nitem('pages', item_symbol.to_s)
11
10
  items[incorporated_topic.identifier.to_s].compiled_content
12
11
  end
13
12
 
14
13
  def include_background(item_symbol)
15
- incorporated_topic = lookup_nitem("background", item_symbol.to_s)
14
+ incorporated_topic = lookup_nitem('background', item_symbol.to_s)
16
15
  items[incorporated_topic.identifier.to_s].compiled_content
17
16
  end
18
17
 
19
18
  def include_intro(item_symbol)
20
- incorporated_topic = lookup_nitem("intro", item_symbol.to_s)
19
+ incorporated_topic = lookup_nitem('intro', item_symbol.to_s)
21
20
  items[incorporated_topic.identifier.to_s].compiled_content
22
21
  end
23
22
 
@@ -47,69 +46,94 @@ module ContentHelpers
47
46
  " *#{string}*{: style=\"color: red\"} "
48
47
  end
49
48
 
50
- def ir(string); italic_red(string); end
49
+ def ir(string)
50
+ italic_red(string)
51
+ end
51
52
 
52
- def callout_1(title, body)
53
+ def callout1(title, body)
53
54
  <<~HTMLSTRING
54
- <div class="well well-sm">
55
+ <div class="well well-sm callout">
55
56
  <span class="themebg label label-primary">#{title}</span>#{body}
56
57
  </div>
57
58
  HTMLSTRING
58
59
  end
59
60
 
60
- def callout(title, body)
61
+ def callout2(title, body)
61
62
  <<~HTMLSTRING
62
- <div class="border border-primary rounded p-2 m-3">
63
+ <div class="callout border border-primary rounded p-2 m-3">
63
64
  <span class="badge badge-pill badge-primary">#{title}</span>#{body}
64
65
  </div>
65
66
  HTMLSTRING
66
67
  end
67
68
 
69
+ def callout(title, body, style=:big)
70
+ if (style == :big)
71
+ %(<div class="jumbotron py-1 border border-primary border-rounded-lg">
72
+ <h1 class="display-5">#{title}</h1>
73
+ <p class="lead">#{body}</p></div>)
74
+ elsif (style == :small)
75
+ <<~HTMLSTRING
76
+ <div class="callout border border-primary rounded p-2 m-3">
77
+ <span class="badge badge-pill badge-primary">#{title}</span>#{body}
78
+ </div>
79
+ HTMLSTRING
80
+ end
81
+ "error in callout call."
82
+ end
83
+
84
+ def iconbadge1(icon, tooltip)
85
+ %(<img src="/bootstrap/bootstrap-icons-1.0.0/#{icon}.svg" title="#{tooltip}" class="iconbadge">)
86
+ end
87
+
88
+ def iconbadge(icon, tooltip)
89
+ %(<svg class="bi iconbadge" title="#{tooltip}" data-placement="top" data-title="#{tooltip}" data-toggle="tooltip" fill="blue"><use xlink:href="/bootstrap/bootstrap-icons-1.0.0/bootstrap-icons.svg##{icon}"/></svg>)
90
+ end
91
+
68
92
  def textbadge(text, tooltip)
69
93
  %(<span class="label label-info" data-toggle="tooltip" data-placement="top" title="#{tooltip}">#{text}</span>)
70
94
  end
71
95
 
72
- def iconbadge(icon, tooltip)
96
+ def iconbadge2(icon, tooltip)
73
97
  %(<span class="fas fa-#{icon} themefg" data-toggle="tooltip" data-placement="top" title="#{tooltip}"></span>)
74
98
  end
75
99
 
76
100
  def pdfbadge
77
- iconbadge("file-pdf", "Submit as 1 page pdf, include name and homework #")
101
+ iconbadge('file-earmark-richtext-fill', 'Submit a pdf file')
78
102
  end
79
103
 
80
104
  def codebadge
81
- iconbadge("code", "Work on code in your portfolio")
105
+ iconbadge('file-code-fill', 'Work on code in your portfolio')
82
106
  end
83
107
 
84
108
  def cloudbadge
85
- iconbadge("cloud-upload-alt", "Work on code in your portfolio")
109
+ iconbadge('cloud-fill', 'Work on code in your portfolio')
86
110
  end
87
111
 
88
112
  def zipbadge
89
- iconbadge("briefcase", "Submit work as an attachment")
113
+ iconbadge('file-earmark-zip-fill', 'Submit work as an attachment')
90
114
  end
91
115
 
92
116
  def partbadge
93
- iconbadge("hand-peace", "Graded for participation only - pass/fail")
117
+ iconbadge('heart-half', 'Graded for participation only - pass/fail')
94
118
  end
95
119
 
96
120
  def timebadge
97
- iconbadge("coffee", "Must be submitted first thing on day of class")
121
+ iconbadge('alarm-fill', 'Must be submitted first thing on day of class')
98
122
  end
99
123
 
100
124
  def teambadge
101
- iconbadge("handshake", "Team Deliverable")
125
+ iconbadge('people-fill', 'Team Deliverable')
102
126
  end
103
127
 
104
128
  def include_image_old(filename_string, extra_class: nil)
105
- css_class = "img-responsive"
106
- css_class += " img-" + extra_class unless extra_class.nil?
129
+ css_class = 'img-responsive'
130
+ css_class += ' img-' + extra_class unless extra_class.nil?
107
131
  <<-HTMLSTRING
108
132
  <img src="#{filename_string}" class=\"%s\" />" % css_class
109
133
  HTMLSTRING
110
134
  end
111
135
 
112
- def include_image(filename_string, extra: "")
136
+ def include_image(filename_string, extra: '')
113
137
  <<~HTMLSTRING
114
138
  <div class="row">
115
139
  <div class="col-md-offset-2 col-md-8">
@@ -119,13 +143,13 @@ module ContentHelpers
119
143
  HTMLSTRING
120
144
  end
121
145
 
122
- def image(filename_string, extra: "")
123
- <<-HTMLSTRING
124
- <img src="/content/topics/images/#{filename_string}" class="img-responsive img-thumbnail" #{extra}/>
146
+ def image(filename_string, extra: '')
147
+ <<~HTMLSTRING
148
+ <img src="/content/topics/images/#{filename_string}" class="img-responsive img-thumbnail" #{extra}/>
125
149
  HTMLSTRING
126
150
  end
127
151
 
128
- def important(string = ":")
152
+ def important(string = ':')
129
153
  <<-HTMLSTRING
130
154
  <div class="cg-important">
131
155
  #{string}
@@ -133,26 +157,26 @@ module ContentHelpers
133
157
  HTMLSTRING
134
158
  end
135
159
 
136
- def nb(string = ":")
160
+ def nb(string = ':')
137
161
  <<-HTMLSTRING
138
162
  <div class="label label-info">#{string}</div>
139
163
  HTMLSTRING
140
164
  end
141
165
 
142
- def tbd(string = "")
166
+ def tbd(string = '')
143
167
  "*[TO BE DETERMINED#{string}]*{: style=\"color: red\"}"
144
168
  end
145
169
 
146
- def deliverable(string, append = "")
170
+ def deliverable(string, append = '')
147
171
  "*Deliverable:*{: style=\"color: red\"} #{string + append} "
148
172
  end
149
173
 
150
174
  def deliverable_po(string)
151
- deliverable(string, " *(graded for participation only)*")
175
+ deliverable(string, ' *(graded for participation only)*')
152
176
  end
153
177
 
154
178
  def deliverable_popdf(string)
155
- deliverable(string, " *(pdf with name and hw number, graded for participation only)*")
179
+ deliverable(string, ' *(pdf with name and hw number, graded for participation only)*')
156
180
  end
157
181
 
158
182
  def team_deliverable(string)
@@ -168,54 +192,84 @@ module ContentHelpers
168
192
  end
169
193
 
170
194
  def homework_hdr(show_legend: :on)
171
- body = "#### Homework due for today"
195
+ body = '## Homework due for today'
172
196
  legend = "\n**Legend**: #{partbadge}: Participation (pass/fail) | #{pdfbadge}: PDF | #{teambadge}: Team | #{zipbadge}: Attachment"
173
197
  body += legend if show_legend == :on
174
198
  body
175
199
  end
176
200
 
177
- def carousel(filenames)
178
- body = %(<div id="myCarousel" class="carousel slide" style="width: 500px; margin: 0 auto;">
179
- <div class="carousel-inner" style="margin: 20px; ">)
180
- counter = 0
181
- filenames.each do |nam|
182
- body << counter == 0 ? %(div class="item active">) : body << %(<div class="item">~
183
- body << %~<img src=")
184
- body << "/content/images/#{nam}"
185
- body << %(" class="img-polaroid" alt=""></div>)
186
- counter += 1
187
- end
188
- body << %(</div> <a class="left carousel-control" href="#myCarousel" data-slide="prev">‹</a>
189
- <a class="right carousel-control" href="#myCarousel" data-slide="next">›</a>
190
- </div>)
191
- body
192
- end
193
-
194
- def carousel_new(filenames)
195
- carousel_work(filenames.map { |filename| "/content/topics/images/" + filename })
196
- end
197
-
198
- def carousel_work(filenames)
199
- body = %(<div id="myCarousel" class="carousel slide" data-ride="carousel" style="width: 500px; margin: 0 auto;">
200
- <div class="carousel-inner" role="listbox" style="margin: 20px; ">)
201
- counter = 0
202
- filenames.each do |nam|
203
- ci = counter == 0 ? %(<div class="item active">) : %(<div class="item">)
204
- body << ci
205
- body << %(<img src=")
206
- body << nam
207
- body << %("/>"></div>)
208
- counter += 1
201
+ # def carousel(filenames)
202
+ # body = %(<div id="myCarousel" class="carousel slide" style="width: 500px; margin: 0 auto;">
203
+ # <div class="carousel-inner" style="margin: 20px; ">)
204
+ # counter = 0
205
+ # filenames.each do |nam|
206
+ # body << counter == 0 ? %(div class="item active">) : body << %(<div class="item">~
207
+ # body << %~<img src=")
208
+ # body << "/content/images/#{nam}"
209
+ # body << %(" class="img-polaroid" alt=""></div>)
210
+ # counter += 1
211
+ # end
212
+ # body << %(</div> <a class="left carousel-control" href="#myCarousel" data-slide="prev"></a>
213
+ # <a class="right carousel-control" href="#myCarousel" data-slide="next"></a>
214
+ # </div>)
215
+ # body
216
+ # end
217
+
218
+ # def carousel_new(filenames)
219
+ # carousel_work(filenames.map { |filename| "/content/topics/images/" + filename })
220
+ # end
221
+
222
+ # def carousel_work(filenames)
223
+ # body = %(<div id="myCarousel" class="carousel slide" data-ride="carousel" style="width: 500px; margin: 0 auto;">
224
+ # <div class="carousel-inner" role="listbox" style="margin: 20px; ">)
225
+ # counter = 0
226
+ # filenames.each do |nam|
227
+ # ci = counter == 0 ? %(<div class="item active">) : %(<div class="item">)
228
+ # body << ci
229
+ # body << %(<img src=")
230
+ # body << nam
231
+ # body << %("/>"></div>)
232
+ # counter += 1
233
+ # end
234
+ # body << %(</div> <a class="left carousel-control" role="button" href="#myCarousel" data-slide="prev">
235
+ # <span class="glyphicon glyphicon-chevron-left"></span>
236
+ # <span class="sr-only">Previous</span>
237
+ # </a>
238
+ # <a class="right carousel-control" role="button" href="#myCarousel" data-slide="next">
239
+ # <span class="glyphicon glyphicon-chevron-right"></span>
240
+ # <span class="sr-only">Next</span>
241
+ # </a>
242
+ # </div>)
243
+ # body
244
+ # end
245
+
246
+ def carousel_v4(filenames)
247
+ body = <<~HEREDOC
248
+ <div id="carouselExampleControls" class="carousel slide" data-ride="carousel">
249
+ <div class="carousel-inner">
250
+ HEREDOC
251
+ count = 0
252
+ filenames.each do |fname|
253
+ active = count == 0 ? 'active' : ''
254
+ body << <<~HEREDOC
255
+ <div class="carousel-item #{active}">
256
+ <img class="d-block w-80" src="/content/topics/images/#{fname}">
257
+ </div>
258
+ HEREDOC
259
+ count += 1
209
260
  end
210
- body << %(</div> <a class="left carousel-control" role="button" href="#myCarousel" data-slide="prev">
211
- <span class="glyphicon glyphicon-chevron-left"></span>
212
- <span class="sr-only">Previous</span>
213
- </a>
214
- <a class="right carousel-control" role="button" href="#myCarousel" data-slide="next">
215
- <span class="glyphicon glyphicon-chevron-right"></span>
216
- <span class="sr-only">Next</span>
217
- </a>
218
- </div>)
261
+ body << <<~HEREDOC
262
+ </div>
263
+ <a class="carousel-control-prev" href="#carouselExampleControls" role="button" data-slide="prev">
264
+ <span class="carousel-control-prev-icon" aria-hidden="true"></span>
265
+ <span class="sr-only">Previous</span>
266
+ </a>
267
+ <a class="carousel-control-next" href="#carouselExampleControls" role="button" data-slide="next">
268
+ <span class="carousel-control-next-icon" aria-hidden="true"></span>
269
+ <span class="sr-only">Next</span>
270
+ </a>
271
+ </div>
272
+ HEREDOC
219
273
  body
220
274
  end
221
275
 
@@ -244,13 +298,13 @@ module ContentHelpers
244
298
  end
245
299
 
246
300
  def include_ruby(name)
247
- filename = Dir.pwd + "/content/content/topics/scripts/" + name.to_s + ".rb"
301
+ filename = Dir.pwd + '/content/content/topics/scripts/' + name.to_s + '.rb'
248
302
  filecontents = File.new(filename).read
249
303
  ruby_string filecontents
250
304
  end
251
305
 
252
306
  def include_python(name)
253
- filename = Dir.pwd + "/content/content/topics/robotcode/" + name.to_s + ".py"
307
+ filename = Dir.pwd + '/content/content/topics/robotcode/' + name.to_s + '.py'
254
308
  filecontents = File.new(filename).read
255
309
  ruby_string filecontents
256
310
  end
@@ -259,11 +313,9 @@ module ContentHelpers
259
313
  "\n~~~~~~"
260
314
  end
261
315
 
262
- def code_end(lang = "")
316
+ def code_end(lang = '')
263
317
  str = "~~~~~~\n"
264
- if ["ruby", "css", "java", "html"].include? lang
265
- str += "{: .language-#{lang}}"
266
- end
318
+ str += "{: .language-#{lang}}" if %w[ruby css java html].include? lang
267
319
  str
268
320
  end
269
321
 
@@ -272,52 +324,64 @@ module ContentHelpers
272
324
  end
273
325
 
274
326
  def include_code(name)
275
- filename = Dir.pwd + "/content/content/topics/scripts/" + name
327
+ filename = Dir.pwd + '/content/content/topics/scripts/' + name
276
328
  filecontents = File.new(filename).read
277
329
  code_string filecontents
278
330
  end
279
331
 
280
- def postit_begin title
281
- "<div class=\"postit\">" + "<h5>" + title + "</h5>"
332
+ def source_begin(language)
333
+ "<pre class=\"#{language}\">"
334
+ end
335
+
336
+ def source_end
337
+ '</pre>'
338
+ end
339
+
340
+ def postit_begin(title)
341
+ '<div class="postit">' + '<h5>' + title + '</h5>'
282
342
  end
283
343
 
284
344
  def postit_end
285
- "</div>"
345
+ '</div>'
286
346
  end
287
347
 
288
348
  def ul_begin
289
- "<ul>"
349
+ '<ul>'
290
350
  end
291
351
 
292
352
  def ul_end
293
- "</ul>"
353
+ '</ul>'
294
354
  end
295
355
 
296
- def ul body
356
+ def ul(body)
297
357
  "<ul>#{body}</ul>"
298
358
  end
299
359
 
300
- def list_items *items
301
- items.reduce("") do |s, i|
302
- if i.start_with?("<ul>")
360
+ def slide
361
+ '<slide_break></slide_break>'
362
+ end
363
+
364
+ def list_items(*items)
365
+ items.reduce('') do |s, i|
366
+ if i.start_with?('<ul>')
303
367
  s + i
304
368
  else
305
- s + "<li>" + i + "</li>"
369
+ s + '<li>' + i + '</li>'
306
370
  end
307
371
  end
308
372
  end
309
373
 
310
374
  def lab_note(title)
311
- "<h5 style=\"font-family:'Permanent Marker'; font-szie:18px; color: red;\">#{title}</h5>"
375
+ "<h3 style=\"font-family:'Permanent Marker'; font-szie:18px; color: red;\">#{title}</h3>"
312
376
  end
313
377
 
314
378
  def toasty(header, *items)
315
- str = %Q(<div class="border border-info rounded w-75 mx-auto p-2 m-3">
379
+ str = %(<div class="border border-info rounded w-75 mx-auto p-2 m-3">
316
380
  <h5>#{header}</h5><ul>)
317
381
  items.each do |itm|
318
- str += "<li>" + itm + "</li>"
382
+ str += '<li>' + itm + '</li>'
319
383
  end
320
- str += "</ul></div>"
384
+ str += '</ul></div>'
321
385
  str
322
386
  end
323
387
  end