diff options
-rw-r--r-- | lib/html.rb | 13 | ||||
-rw-r--r-- | lib/latex.rb | 17 | ||||
-rw-r--r-- | lib/ly.rb | 14 | ||||
-rw-r--r-- | lib/pather.rb | 39 | ||||
-rw-r--r-- | lib/recording.rb | 36 | ||||
-rw-r--r-- | lib/song.rb | 47 | ||||
-rw-r--r-- | lib/songs.rb | 19 | ||||
-rw-r--r-- | lib/statics.rb | 10 | ||||
-rw-r--r-- | lib/templated.rb | 20 | ||||
-rw-r--r-- | lib/util.rb | 85 | ||||
-rw-r--r-- | ly/preamble.ly | 12 | ||||
-rw-r--r-- | scripts/build.rb | 31 | ||||
-rw-r--r-- | src/index.html.erb | 9 | ||||
-rw-r--r-- | src/style.css | 31 |
14 files changed, 383 insertions, 0 deletions
diff --git a/lib/html.rb b/lib/html.rb new file mode 100644 index 0000000..61e25a3 --- /dev/null +++ b/lib/html.rb @@ -0,0 +1,13 @@ +require './lib/templated' + +def render_html song + template = html_template 'song' + template.result binding +end + +def make_htmls songs + songs.each do |song_id, song| + content = render_html song + write_templated content, song_html(song_id), song.title + end +end diff --git a/lib/latex.rb b/lib/latex.rb new file mode 100644 index 0000000..e17a6ef --- /dev/null +++ b/lib/latex.rb @@ -0,0 +1,17 @@ +def render_latex song + template = tex_template 'song' + templated = template.result binding + File.write(tmp(song_tex song.id), templated) +end + +def render_pdf song + render_latex song + system "lualatex --shell-escape -output-directory=#{TmpDir}/#{SongsDir} #{tmp (song_tex song.id)}" + system "mv #{tmp (song_pdf song.id)} #{build (song_pdf song.id)}" +end + +def make_pdfs songs + songs.each_value do |song| + render_pdf song + end +end diff --git a/lib/ly.rb b/lib/ly.rb new file mode 100644 index 0000000..fc85204 --- /dev/null +++ b/lib/ly.rb @@ -0,0 +1,14 @@ +def compile_ly ly_filename + system "lilypond --svg --output=#{tmp SongsDir} #{ly_filename}" + system "lilypond --output=#{tmp SongsDir} #{ly_filename}" +end + +def make_sheets songs + songs.keys.each do |song_id| + ly_filename = src(song_ly song_id) + if File.file? ly_filename + compile_ly ly_filename + system "mv #{tmp (song_tmp_svg song_id)} #{build(song_svg song_id)}" + end + end +end diff --git a/lib/pather.rb b/lib/pather.rb new file mode 100644 index 0000000..1f59df0 --- /dev/null +++ b/lib/pather.rb @@ -0,0 +1,39 @@ +class Pather + attr_accessor :current_path + def initialize + @assets = {} + @current_path = [] + end + + def add asset_id, path + @assets[asset_id] = @current_path + path.split('/') + end + + def path_to asset_id + other_path = @assets[asset_id] + find_path_between @current_path, other_path + end + + def find_path_between from, to + from, to = drop_common_prefix from, to + path = ('../' * from.length) + to.join('/') + end + + def drop_common_prefix path1, path2 + common_prefix_length = path1.zip(path2).take_while do |(segment1, segment2)| + segment1 == segment2 + end.length + + return path1[common_prefix_length..], path2[common_prefix_length..] + end + + def cd path + path.split('/').each do |segment| + if segment == '..' + @current_path.pop + else + @current_path.push segment + end + end + end +end diff --git a/lib/recording.rb b/lib/recording.rb new file mode 100644 index 0000000..d1d7683 --- /dev/null +++ b/lib/recording.rb @@ -0,0 +1,36 @@ +class NotImplemented < Exception +end + +class Recording + def render + raise NotImplemented + end +end + +class YouTubeRecording + attr_accessor :vid + def initialize link + @vid = parse_vid link + end + + def parse_vid link + /\?v=(.{11})/.match(link)[1] + end + + def render + template = ERB.new(File.read('templates/youtube.html.erb'), trim_mode: '-') + template.result binding + end +end + +class BandcampRecording + attr_accessor :link + def initialize link + @link = link + end + + def render + template = ERB.new(File.read('templates/bandcamp.html.erb'), trim_mode: '-') + template.result binding + end +end diff --git a/lib/song.rb b/lib/song.rb new file mode 100644 index 0000000..4076956 --- /dev/null +++ b/lib/song.rb @@ -0,0 +1,47 @@ +require 'yaml' + +require './lib/recording' + +class Song + attr_accessor :title, :id, :lyrics, :recordings + def initialize title, id + @title = title + @id = id + @recordings = [] + end + + def self.from_yaml song_id + metadata = YAML.load(File.read(src(song_meta song_id))) + song = Song.new metadata['title'], song_id + + song.lyrics = nil + lyrics_file = src (song_lyrics song_id) + if File.file? lyrics_file + song.lyrics = File.read lyrics_file + end + + if metadata['recordings'] + metadata['recordings'].each do |recording| + if recording['type'] == 'youtube' + song.recordings.push YouTubeRecording.new(recording['link']) + elsif recording['type'] == 'bandcamp' + song.recordings.push BandcampRecording.new(recording['link']) + end + end + end + song + end + + def split_lyrics + @lyrics.split("\n\n").map { |paragraph| paragraph.split "\n" } + end + + def render_sheet_music + if File.file? (src (song_ly id)) + template = ERB.new(File.read('templates/sheet_music.html.erb'), trim_mode: '-') + template.result binding + else + "" + end + end +end diff --git a/lib/songs.rb b/lib/songs.rb new file mode 100644 index 0000000..aa519e1 --- /dev/null +++ b/lib/songs.rb @@ -0,0 +1,19 @@ +require 'set' + +require './lib/util' + +@songs = nil + +def get_song_ids dir + ids = Set.new + Dir.new(src SongsDir).children.each do |filename| + ids.add(File.basename filename, '.*') + end + ids +end + +def songs + @songs ||= get_song_ids(SongsDir).map do |song_id| + [song_id, Song.from_yaml(song_id)] + end.to_h +end diff --git a/lib/statics.rb b/lib/statics.rb new file mode 100644 index 0000000..24ca9d6 --- /dev/null +++ b/lib/statics.rb @@ -0,0 +1,10 @@ +require 'fileutils' + +def write_statics statics + statics = statics.each do |filename| + source = src filename + target = build filename + FileUtils.mkdir_p(File.dirname target) + FileUtils.cp_r source, target + end +end diff --git a/lib/templated.rb b/lib/templated.rb new file mode 100644 index 0000000..548352c --- /dev/null +++ b/lib/templated.rb @@ -0,0 +1,20 @@ +def write_templated_file content_filename, title + content = File.read(src content_filename) + write_templated content, content_filename, title +end + +def write_erb erb_filename + content = ERB.new(File.read(src erb_filename)).result + cut_filename = erb_filename.sub /\.erb$/, '' + File.write build(cut_filename), content +end + +def write_templated_erb erb_filename, title = nil + content = ERB.new(File.read(src erb_filename), trim_mode: '-').result + cut_filename = erb_filename.sub /\.erb$/, '' + write_templated content, cut_filename, title +end + +def write_templated content, filename, title = nil + File.write build(filename), page_template.result(binding) +end diff --git a/lib/util.rb b/lib/util.rb new file mode 100644 index 0000000..48698ff --- /dev/null +++ b/lib/util.rb @@ -0,0 +1,85 @@ +SongsDir = 'songs' +SrcDir = 'src' +BuildDir = 'public' +TmpDir = 'tmp' +TemplatesDir = 'templates' + +def song filename + File.join SongsDir, filename +end + +def build filename + File.join BuildDir, filename +end + +def tmp filename + File.join TmpDir, filename +end + +def src filename + File.join SrcDir, filename +end + +def song_lyrics song_id + song "#{song_id}.txt" +end + +def song_ly song_id + song "#{song_id}.ly" +end + +def song_meta song_id + song "#{song_id}.yaml" +end + +def song_tex song_id + song "#{song_id}.tex" +end + +def song_sheet_pdf song_id + song "#{song_id}.cropped.pdf" +end + +def song_tmp_svg song_id + song "#{song_id}.cropped.svg" +end + +def song_pdf song_id + song "#{song_id}.pdf" +end + +def song_sheet_svg song_id + song "#{song_id}.svg" +end + +def song_svg song_id + song "#{song_id}.svg" +end + +def song_html song_id + song "#{song_id}.html" +end + +def template filename + ERB.new(File.read(filename), trim_mode: '-') +end + +def template_file filename + File.join TemplatesDir, filename +end + +def tex_template name + template(template_file "#{name}.tex.erb") +end + +def html_template name + template(template_file "#{name}.html.erb") +end + +def page_template + html_template 'template' +end + +def path_to asset_id + P.path_to asset_id +end diff --git a/ly/preamble.ly b/ly/preamble.ly new file mode 100644 index 0000000..437ee5e --- /dev/null +++ b/ly/preamble.ly @@ -0,0 +1,12 @@ +\version "2.22.1" + +#(ly:set-option 'print-pages #f) +#(ly:set-option 'crop #t) + +\header { + tagline = ##f +} + +\paper { + indent = 0 +} diff --git a/scripts/build.rb b/scripts/build.rb new file mode 100644 index 0000000..1ad5472 --- /dev/null +++ b/scripts/build.rb @@ -0,0 +1,31 @@ +require 'erb' + +require './lib/song' +require './lib/songs' +require './lib/tags' +require './lib/latex' +require './lib/pather' +require './lib/ly' +require './lib/html' +require './lib/statics' + +statics = [ 'style.css' ] + +P = Pather.new + +P.add 'index', 'index.html' +P.add 'style', 'style.css' + +songs.each_key do |song_id| + P.add(song_html(song_id), song_html(song_id)) + P.add(song_svg(song_id), song_svg(song_id)) + P.add(song_pdf(song_id), song_pdf(song_id)) +end + +write_templated_erb 'index.html.erb' +write_statics statics + +P.cd SongsDir +make_sheets songs +make_pdfs songs +make_htmls songs diff --git a/src/index.html.erb b/src/index.html.erb new file mode 100644 index 0000000..2008d11 --- /dev/null +++ b/src/index.html.erb @@ -0,0 +1,9 @@ +Ĺšpiewnik polskiej muzyki tradycyjnej. + +<ul> +<%- songs.each_value do |song| -%> + <li> + <a href='<%= path_to (song_html song.id) %>'><%= song.title %></a> + </li> +<%- end -%> +</ul> diff --git a/src/style.css b/src/style.css new file mode 100644 index 0000000..f6ec3cc --- /dev/null +++ b/src/style.css @@ -0,0 +1,31 @@ +body { + margin: 40px auto; + max-width: 800px; + line-height: 1.6; + font-size: 18px; + padding: 0 10px; +} + +a { + color: darkblue; + text-decoration: none; +} + +a:hover { + color: #55f; +} + +ul { + list-style-type: ''; + column-count: 3; +} + +li { + margin-top: 10px; + margin-bottom: 10px; + padding-left: 0.7em; +} + +h1, h2, h3 { + line-height: 1.2 +} |