diff --git a/exe/referator b/exe/referator index 23f5df6..f309a34 100755 --- a/exe/referator +++ b/exe/referator @@ -17,6 +17,14 @@ def parse_command(line) [command, rest].freeze end +def success(data = nil) + puts "OK #{data.to_json}" +end + +def failure(msg) + puts "ERR #{String(msg).lines.join(' ')}" +end + workdir = ARGV.first workdir = Dir.pwd if String(workdir).strip.empty? workdir = File.expand_path(workdir).freeze @@ -25,39 +33,49 @@ config = Referator::Config.new workdir footnotes = Referator::Footnotes.new config while (line = $stdin.gets) - command, rest = parse_command line - case command - when 'REGISTER_FORMAT' - data = JSON.parse rest - config.formats.register( - String(data['name']).to_sym, - **data.except('name').transform_keys(&:to_sym), - ) - when 'REGISTER_KIND' - data = JSON.parse rest - config.kinds.register String(data).to_sym - when 'ADD_REF' - data = JSON.parse rest - config.repo.add_ref(**data.transform_keys(&:to_sym)) - when 'ADD_NOTE' - config.freeze - data = JSON.parse rest - puts footnotes.add_note( - String(data['kind']).to_sym, - String(data['id']), - ).to_h.to_json - when 'REF' - config.freeze - data = JSON.parse rest - puts config.repo[ - String(data['kind']).to_sym, - String(data['id']), - ].to_h.to_json - when 'RENDER_FOOTNOTES' - config.freeze - data = JSON.parse rest - puts footnotes.render(String(data).to_sym).to_json - else - raise 'Invalid command' + begin + command, rest = parse_command line + case command + when 'EXIT' + success + exit + when 'REGISTER_FORMAT' + data = JSON.parse rest + config.formats.register( + String(data['name']).to_sym, + **data.except('name').transform_keys(&:to_sym), + ) + success + when 'REGISTER_KIND' + data = JSON.parse rest + config.kinds.register String(data).to_sym + success + when 'ADD_REF' + data = JSON.parse rest + config.repo.add_ref(**data.transform_keys(&:to_sym)) + success + when 'ADD_NOTE' + config.freeze + data = JSON.parse rest + success footnotes.add_note( + String(data['kind']).to_sym, + String(data['id']), + ).to_h + when 'REF' + config.freeze + data = JSON.parse rest + success config.repo[ + String(data['kind']).to_sym, + String(data['id']), + ].to_h + when 'RENDER_FOOTNOTES' + config.freeze + data = JSON.parse rest + success String footnotes.render String(data).to_sym + else + raise 'Invalid command' + end + rescue => e + failure e.detailed_message end end diff --git a/test.rb b/test.rb new file mode 100755 index 0000000..2695fb9 --- /dev/null +++ b/test.rb @@ -0,0 +1,119 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require 'json' +require 'open3' + +EXE = File.expand_path('exe/referator', __dir__).freeze + +@stdin, @stdout, @wait_thr = Open3.popen2 EXE, chdir: __dir__ + +@stdin.sync = true +@stdout.sync = true + +at_exit do + @stdin.close + @stdout.close + raise 'Script error' unless @wait_thr.value.success? +end + +def cmd(name, data) + @stdin.puts "#{name} #{data.to_json}" + result = @stdout.gets.chomp + if result.start_with? 'OK ' + JSON.parse(result[3..]).freeze + elsif result.start_with? 'ERR ' + raise "Error response: #{result[4..]}" + else + raise 'Invalid response' + end +end + +cmd :REGISTER_KIND, :self +cmd :REGISTER_KIND, :link + +cmd :REGISTER_FORMAT, { name: :html, + args: ['test/footnotes.rb', { format: nil }], + stdin: { notes: nil } } + +cmd :ADD_REF, + { kind: :self, + id: '/blog/foo', + slug: 'blog-foo', + text: 'Foo' } +cmd :ADD_REF, + { kind: :self, + id: '/blog/bar', + slug: 'blog-bar', + text: 'Bar' } +cmd :ADD_REF, + { kind: :link, + id: :example_com, + slug: 'example-com', + url: 'https://example.com', + text: 'Example Domain' } +cmd :ADD_REF, + { kind: :link, + id: :causa_arcana_com, + slug: 'causa-arcana-com', + url: 'https://causa-arcana.com', + text: 'Causa Arcana' } + +cmd(:REF, { kind: :self, id: '/blog/foo' }).tap do |result| + expected = { + 'kind' => 'self', + 'id' => '/blog/foo', + 'slug' => 'blog-foo', + 'anchor' => 'self-blog-foo', + 'fragment' => '#self-blog-foo', + 'text' => 'Foo', + } + + raise unless result == expected +end +cmd(:REF, { kind: :link, id: :example_com }).tap do |result| + expected = { + 'kind' => 'link', + 'id' => 'example_com', + 'slug' => 'example-com', + 'anchor' => 'link-example-com', + 'fragment' => '#link-example-com', + 'url' => 'https://example.com', + 'text' => 'Example Domain', + } + + raise unless result == expected +end + +cmd :ADD_NOTE, { kind: :self, id: '/blog/foo' } +cmd :ADD_NOTE, { kind: :link, id: :example_com } +cmd :ADD_NOTE, { kind: :self, id: '/blog/bar' } +cmd :ADD_NOTE, { kind: :link, id: :causa_arcana_com } + +cmd(:RENDER_FOOTNOTES, :html).tap do |result| + expected = <<~HTML.freeze +

Self references

+ +
    +
  1. + Foo +
  2. +
  3. + Bar +
  4. +
+ +

Link references

+ +
    + + +
+ HTML + + raise unless result == expected +end diff --git a/test/footnotes.html.erb b/test/footnotes.html.erb new file mode 100644 index 0000000..0fe7170 --- /dev/null +++ b/test/footnotes.html.erb @@ -0,0 +1,24 @@ +<% if notes.any? { |note| note['kind'] == 'self' } -%> + +

Self references

+ +
    +<% notes.select { |note| note['kind'] == 'self' }.each do |note| -%> +
  1. + <%= note['text'] %> +
  2. +<% end -%> +
+<% end -%> +<% if notes.any? { |note| note['kind'] == 'link' } -%> + +

Link references

+ +
    +<% notes.select { |note| note['kind'] == 'link' }.each do |note| -%> +
  1. + <%= note['text'] %> +
  2. +<% end -%> +
+<% end -%> diff --git a/test/footnotes.rb b/test/footnotes.rb new file mode 100755 index 0000000..44d5964 --- /dev/null +++ b/test/footnotes.rb @@ -0,0 +1,17 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require 'erb' +require 'json' +require 'pathname' + +def template(filename) + pathname = Pathname.new(__dir__).join(filename).expand_path.freeze + ERB.new(pathname.read, trim_mode: '-').tap do |erb| + erb.filename = pathname.to_s.freeze + end.freeze +end + +puts template("footnotes.#{ARGV.first}.erb").result_with_hash( + notes: JSON.parse($stdin.read), +).strip