songbooks 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +5 -0
  5. data/Gemfile +4 -0
  6. data/Guardfile +29 -0
  7. data/LICENSE +22 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +41 -0
  10. data/Rakefile +6 -0
  11. data/app/assets/javascripts/application.coffee +4 -0
  12. data/app/assets/javascripts/components/filters/convertWhitespace.filter.coffee +3 -0
  13. data/app/assets/javascripts/components/song_component/chord.directive.coffee +9 -0
  14. data/app/assets/javascripts/components/song_component/literal.directive.coffee +6 -0
  15. data/app/assets/javascripts/components/song_component/song_component.directive.coffee +6 -0
  16. data/app/assets/javascripts/components/songbook/songbook.controller.coffee +29 -0
  17. data/app/assets/javascripts/components/songs/song.controller.coffee +10 -0
  18. data/app/assets/javascripts/components/songs/song.directive.coffee +7 -0
  19. data/app/assets/javascripts/components/songs/song.service.coffee +98 -0
  20. data/app/assets/javascripts/components/songs/songs.controller.coffee +21 -0
  21. data/app/assets/javascripts/routes.coffee +11 -0
  22. data/app/assets/stylesheets/application.scss +34 -0
  23. data/app/fonts/DejaVuSans-Bold.ttf +0 -0
  24. data/app/fonts/DejaVuSans-BoldOblique.ttf +0 -0
  25. data/app/fonts/DejaVuSans-ExtraLight.ttf +0 -0
  26. data/app/fonts/DejaVuSans-Oblique.ttf +0 -0
  27. data/app/fonts/DejaVuSans.ttf +0 -0
  28. data/app/fonts/DejaVuSansCondensed-Bold.ttf +0 -0
  29. data/app/fonts/DejaVuSansCondensed-BoldOblique.ttf +0 -0
  30. data/app/fonts/DejaVuSansCondensed-Oblique.ttf +0 -0
  31. data/app/fonts/DejaVuSansCondensed.ttf +0 -0
  32. data/app/fonts/DejaVuSansMono-Bold.ttf +0 -0
  33. data/app/fonts/DejaVuSansMono-BoldOblique.ttf +0 -0
  34. data/app/fonts/DejaVuSansMono-Oblique.ttf +0 -0
  35. data/app/fonts/DejaVuSansMono.ttf +0 -0
  36. data/app/fonts/DejaVuSerif-Bold.ttf +0 -0
  37. data/app/fonts/DejaVuSerif-BoldItalic.ttf +0 -0
  38. data/app/fonts/DejaVuSerif-Italic.ttf +0 -0
  39. data/app/fonts/DejaVuSerif.ttf +0 -0
  40. data/app/fonts/DejaVuSerifCondensed-Bold.ttf +0 -0
  41. data/app/fonts/DejaVuSerifCondensed-BoldItalic.ttf +0 -0
  42. data/app/fonts/DejaVuSerifCondensed-Italic.ttf +0 -0
  43. data/app/fonts/DejaVuSerifCondensed.ttf +0 -0
  44. data/app/tex/songbook.tex +12 -0
  45. data/app/views/application.haml +54 -0
  46. data/app/views/layouts/application.haml +40 -0
  47. data/app/views/songbook.prawn +80 -0
  48. data/app/views/songs/component.haml +2 -0
  49. data/app/views/songs/index.jbuilder +5 -0
  50. data/app/views/songs/show.haml +23 -0
  51. data/app/views/songs/show.jbuilder +24 -0
  52. data/app/views/songs/song.haml +4 -0
  53. data/exe/sb_server +6 -0
  54. data/lib/prawn_ext/font/afm.rb +20 -0
  55. data/lib/songbooks.rb +32 -0
  56. data/lib/songbooks/CLI.rb +13 -0
  57. data/lib/songbooks/components/chord.rb +98 -0
  58. data/lib/songbooks/components/literal.rb +57 -0
  59. data/lib/songbooks/components/metadata.rb +69 -0
  60. data/lib/songbooks/components/section.rb +73 -0
  61. data/lib/songbooks/controllers/controller.rb +18 -0
  62. data/lib/songbooks/controllers/songs_controller.rb +30 -0
  63. data/lib/songbooks/folder.rb +32 -0
  64. data/lib/songbooks/server.rb +65 -0
  65. data/lib/songbooks/song.rb +53 -0
  66. data/lib/songbooks/version.rb +3 -0
  67. data/lib/songbooks/view_helper.rb +9 -0
  68. data/public/javascripts/angular-local-storage.js +449 -0
  69. data/public/javascripts/angular-route.js +991 -0
  70. data/public/javascripts/angular.js +28904 -0
  71. data/public/javascripts/application.js +8 -0
  72. data/public/javascripts/components/filters/convertWhitespace.filter.js +8 -0
  73. data/public/javascripts/components/song_component/chord.directive.js +13 -0
  74. data/public/javascripts/components/song_component/literal.directive.js +9 -0
  75. data/public/javascripts/components/song_component/song_component.directive.js +9 -0
  76. data/public/javascripts/components/songbook/songbook.controller.js +33 -0
  77. data/public/javascripts/components/songs/song.controller.js +12 -0
  78. data/public/javascripts/components/songs/song.directive.js +9 -0
  79. data/public/javascripts/components/songs/song.service.js +107 -0
  80. data/public/javascripts/components/songs/songs.controller.js +22 -0
  81. data/public/javascripts/jquery-2.1.4.min.js +4 -0
  82. data/public/javascripts/routes.js +16 -0
  83. data/public/stylesheets/application.css +24 -0
  84. data/public/stylesheets/bootstrap-theme.min.css +5 -0
  85. data/public/stylesheets/bootstrap.min.css +5 -0
  86. data/songbooks.gemspec +51 -0
  87. metadata +369 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d039be80aa91be731b93c15a510600e11e5dcb19
4
+ data.tar.gz: b22174caf5f19f92cb21f6cdc5731659c920e4b0
5
+ SHA512:
6
+ metadata.gz: 8b2144caaa1ca0acc9d29f63d6e27f556053a922a13a4ad824d684c9596bd23d68ac99335593fb28e98aeffdeeb7587a1414229be0be4e1f9393a87c3e19de13
7
+ data.tar.gz: 649206f5dd910096907c2f5c31805f4ca4179754b38c5a5fc5fffc54e93ce91f45559db12287547becca6fdaa2d44ae161489aaa1c2b2b357ee52bc3d2ab262a
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+
11
+ .byebug_history
12
+
13
+ /.sass-cache
14
+ /*.gem
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.1.1
5
+ before_install: gem install bundler -v 1.12.4
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in songbooks.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,29 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ ## Uncomment and set this to only include directories you want to watch
5
+ # directories %w(app lib config test spec features) \
6
+ # .select{|d| Dir.exists?(d) ? d : UI.warning("Directory #{d} does not exist")}
7
+
8
+ ## Note: if you are using the `directories` clause above and you are not
9
+ ## watching the project directory ('.'), then you will want to move
10
+ ## the Guardfile to a watched dir and symlink it back, e.g.
11
+ #
12
+ # $ mkdir config
13
+ # $ mv Guardfile config/
14
+ # $ ln -s config/Guardfile .
15
+ #
16
+ # and, you'll have to watch "config/Guardfile" instead of "Guardfile"
17
+
18
+ coffeescript_options = {
19
+ input: 'app/assets/javascripts',
20
+ output: 'public/javascripts',
21
+ patterns: [%r{^app/assets/javascripts/(.+\.(?:coffee|coffee\.md|litcoffee))$}]
22
+ }
23
+
24
+ guard 'coffeescript', coffeescript_options do
25
+ coffeescript_options[:patterns].each { |pattern| watch(pattern) }
26
+ end
27
+
28
+ guard 'sass', :input => 'app/assets/stylesheets', :output => 'public/stylesheets'
29
+
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Stefan Exner
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Stefan Exner
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,41 @@
1
+ # Songbooks
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/songbooks`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'songbooks'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install songbooks
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/songbooks.
36
+
37
+
38
+ ## License
39
+
40
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
41
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,4 @@
1
+ window.app = angular.module 'songbooks', ['ngRoute', 'LocalStorageModule']
2
+
3
+ app.config (localStorageServiceProvider) ->
4
+ localStorageServiceProvider.setPrefix('songbooks')
@@ -0,0 +1,3 @@
1
+ app.filter 'convertWhitespace', () ->
2
+ (text) ->
3
+ text.replace /[ ]/g, '\u00a0'
@@ -0,0 +1,9 @@
1
+ app.directive 'chord', () ->
2
+ {
3
+ restrict: 'E',
4
+ template: '{{ component.name }}'
5
+ link: (scope, element) ->
6
+ $(element).attr('data-name', scope.component.name)
7
+ $(element).attr('data-transposed-by', scope.component.transposed_by)
8
+ }
9
+
@@ -0,0 +1,6 @@
1
+ app.directive 'literal', () ->
2
+ {
3
+ restrict: 'E',
4
+ template: '{{ component.content | convertWhitespace }}'
5
+ }
6
+
@@ -0,0 +1,6 @@
1
+ app.directive 'songComponent', () ->
2
+ {
3
+ restrict: 'E',
4
+ templateUrl: 'static/songs/component'
5
+ }
6
+
@@ -0,0 +1,29 @@
1
+ app.controller 'SongbookController', ['$http', 'songService', ($http, songService) ->
2
+ @filterQuery = ''
3
+
4
+ @songs = () ->
5
+ songService.selectedSongs
6
+
7
+ @title = () ->
8
+ songService.songbookTitle
9
+
10
+ @addSong = (song) ->
11
+ songService.addSongToBook(song)
12
+
13
+ @removeSong = (song) ->
14
+ songService.removeSongFromBook(song)
15
+
16
+ @clear = () ->
17
+ songService.clearSongbook()
18
+
19
+ @sendToServer = () ->
20
+ $http.post '/songbook',
21
+ 'songs': @songs().map (s) ->
22
+ s.identifier
23
+ .success ->
24
+ window.location.href = '/songbook.pdf'
25
+
26
+ @
27
+ ]
28
+
29
+
@@ -0,0 +1,10 @@
1
+ app.controller 'SongController', ['$routeParams', 'songService', ($routeParams, songService) ->
2
+ songService.loadSong($routeParams.songIdentifier)
3
+
4
+ @song = () ->
5
+ songService.activeSong
6
+
7
+ @
8
+ ]
9
+
10
+
@@ -0,0 +1,7 @@
1
+ app.directive 'song', () ->
2
+ {
3
+ restrict: 'E',
4
+ templateUrl: 'static/songs/song'
5
+ }
6
+
7
+
@@ -0,0 +1,98 @@
1
+ app.service 'songService', ['$http', 'localStorageService', ($http, localStorageService) ->
2
+ @activeSong = null
3
+ @songs = []
4
+ @selectedSongs = []
5
+ @songbookTitle = 'Songbook'
6
+
7
+ #
8
+ # Adds the given song to the current songbook collection
9
+ # This is only done in the browser and won't be submitted to the server
10
+ # until a PDF is requested
11
+ #
12
+ @addSongToBook = (song) ->
13
+ @selectedSongs.push(song) unless @songInCollection(song, @selectedSongs)
14
+ @persistSongbook()
15
+
16
+ #
17
+ # Adds all currently available songs to the songbook
18
+ #
19
+ @addAllToBook = () ->
20
+ angular.forEach @songs, (song) =>
21
+ @selectedSongs.push(song) unless @songInCollection(song, @selectedSongs)
22
+ @persistSongbook()
23
+
24
+ #
25
+ # Removes the given song from the current songbook collection
26
+ # This is only done in the browser and won't be submitted to the server
27
+ # until a PDF is requested
28
+ #
29
+ @removeSongFromBook = (song) ->
30
+ if (idx = @songPositionInCollection(song, @selectedSongs)) > -1
31
+ @selectedSongs.splice(idx, 1)
32
+ @persistSongbook()
33
+
34
+ @setActiveSong = (identifier) ->
35
+ for song in @songs
36
+ if song.identifier == identifier
37
+ @activeSong.active = false if @activeSong
38
+ @activeSong = song
39
+ song.active = true
40
+ break
41
+
42
+ @loadSong = (identifier) ->
43
+ $http.get("/songs/#{identifier}.json").success (response) =>
44
+ @setActiveSong(identifier)
45
+ @activeSong.sections = response.data.sections
46
+
47
+ @loadSongs = () ->
48
+ $http.get('/songs.json').success (response) =>
49
+ @songs = response.data
50
+ @restoreSongbook()
51
+
52
+ #
53
+ # @return [Boolean] +true+ if the song is part of the given collection
54
+ #
55
+ @songInCollection = (song, collection) ->
56
+ @songPositionInCollection(song, collection) > -1
57
+
58
+ #
59
+ # @return [Integer] the array index of the given song within the given collection
60
+ # or -1 if the song is not a part of it.
61
+ #
62
+ @songPositionInCollection = (song, collection) ->
63
+ result = -1
64
+ angular.forEach collection, (s, idx) ->
65
+ result = idx if s.identifier == song.identifier
66
+ result
67
+
68
+ #
69
+ # Loads a previously created songbook from the browser's local storage
70
+ #
71
+ @restoreSongbook = () ->
72
+ if (storedBook = localStorageService.get('songbook'))
73
+ @songbookTitle = storedBook.title
74
+ angular.forEach storedBook.songs, (song) =>
75
+ @selectedSongs.push(song) if @songInCollection(song, @songs)
76
+
77
+ #
78
+ # Saves the current songbook in the browser's local storage
79
+ #
80
+ @persistSongbook = () ->
81
+ localStorageService.set 'songbook',
82
+ 'songs': @selectedSongs
83
+ 'title': @songbookTitle
84
+
85
+ #
86
+ # Clears the local songbook
87
+ # This is only done in the browser and won't be submitted to the server
88
+ # until a PDF is requested
89
+ #
90
+ @clearSongbook = () ->
91
+ @selectedSongs = []
92
+ @songbookTitle = 'Songbook'
93
+ localStorageService.remove('songbook')
94
+
95
+ @
96
+ ]
97
+
98
+
@@ -0,0 +1,21 @@
1
+ app.controller 'SongsController', ['$http', 'songService', '$location', ($http, songService, $location) ->
2
+ songService.loadSongs()
3
+
4
+ @filterQuery = ''
5
+
6
+ @songs = () ->
7
+ songService.songs
8
+
9
+ @setActive = (song) ->
10
+ $location.path("/songs/#{song.identifier}")
11
+
12
+ @activeSong = () ->
13
+ songService.activeSong
14
+
15
+ @addAllToBook = () ->
16
+ songService.addAllToBook()
17
+
18
+ @
19
+ ]
20
+
21
+
@@ -0,0 +1,11 @@
1
+ app.config ['$routeProvider', ($routeProvider) ->
2
+ $routeProvider
3
+ .when '/songs/:songIdentifier',
4
+ title: 'Song',
5
+ templateUrl: 'static/songs/show'
6
+ controller: 'SongController as songCtrl'
7
+ .when '/',
8
+ template: 'Choose a song on the left'
9
+ .otherwise
10
+ redirectTo: '/'
11
+ ]
@@ -0,0 +1,34 @@
1
+ body {
2
+ padding: 10px;
3
+ }
4
+
5
+ #file-list {
6
+ max-height: 500px;
7
+ overflow-x: auto;
8
+ }
9
+
10
+ #songs {
11
+ max-height: 700px;
12
+ overflow: scroll;
13
+ }
14
+
15
+ song-component {
16
+ font-family: "Courier New", Courier, monospace;
17
+ display: inline-block;
18
+ }
19
+
20
+ chord {
21
+ color: darkred;
22
+ }
23
+
24
+ a {
25
+ &[ng-click] {
26
+ cursor: pointer;
27
+ }
28
+ }
29
+
30
+ @media only print {
31
+ .panel {
32
+ border: none;
33
+ }
34
+ }
Binary file
Binary file
Binary file
Binary file