Skip to content

Commit

Permalink
Merge pull request #77 from SwedbankPay/feature/dx-914_fix_page_output
Browse files Browse the repository at this point in the history
DX-914: Only replace the needle
  • Loading branch information
asbjornu authored Nov 5, 2021
2 parents db286ae + 1ac10f9 commit e56aac7
Show file tree
Hide file tree
Showing 5 changed files with 217 additions and 58 deletions.
1 change: 1 addition & 0 deletions .github/scripts/test-gem.sh
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ test_gem() {

file="${workdir}/_site/index.html"

file_contains "${file}" "This is a fixture"
file_contains "${file}" "class=\"${class}\""
file_contains "${file}" "<svg"
file_contains "${file}" "<ellipse"
Expand Down
105 changes: 105 additions & 0 deletions lib/kramdown-plantuml/jekyll_page_processor.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# frozen_string_literal: true

require 'htmlentities'
require 'json'
require_relative 'log_wrapper'

module Kramdown
module PlantUml
# Processes Jekyll pages.
class JekyllPageProcessor
PROCESSED_KEY = :kramdown_plantuml_processed

def initialize(page)
raise ArgumentError, 'page cannot be nil' if page.nil?

puts page.class

@page = page
end

def process(site_destination_directory)
@page.output = do_process
@page.data[PROCESSED_KEY] = true
@page.write(site_destination_directory)
end

def should_process?
return false unless @page.output_ext == '.html'

if !@page.data.nil? && @page.data.key?(PROCESSED_KEY) && @page.data[PROCESSED_KEY]
logger.debug "Skipping #{@page.path} because it has already been processed."
return false
end

true
end

class << self
def needle(plantuml, options)
hash = { 'plantuml' => plantuml, 'options' => options.to_h }

<<~NEEDLE
<!--#kramdown-plantuml.start#-->
#{hash.to_json}
<!--#kramdown-plantuml.end#-->
NEEDLE
rescue StandardError => e
raise e if options.nil? || options.raise_errors?

logger.error 'Error while placing needle.'
logger.error e.to_s
logger.debug_multiline plantuml
end

def logger
@logger ||= ::Kramdown::PlantUml::LogWrapper.init
end
end

private

def do_process
logger.debug "Replacing Jekyll needles in #{@page.path}"

html = @page.output

return html if html.nil? || html.empty? || !html.is_a?(String)

html.gsub(/<!--#kramdown-plantuml\.start#-->(?<json>.*?)<!--#kramdown-plantuml\.end#-->/m) do
json = $LAST_MATCH_INFO ? $LAST_MATCH_INFO[:json] : nil
replace_needle(json) unless json.nil?
end
end

def replace_needle(json)
logger.debug 'Replacing Jekyll needle.'

needle_hash = JSON.parse(json)
options_hash = needle_hash['options']
options = ::Kramdown::PlantUml::Options.new({ plantuml: options_hash })

begin
decode_and_convert(needle_hash, options)
rescue StandardError => e
raise e if options.raise_errors?

logger.error 'Error while replacing Jekyll needle.'
logger.error e.to_s
logger.debug_multiline json
end
end

def decode_and_convert(hash, options)
encoded_plantuml = hash['plantuml']
plantuml = HTMLEntities.new.decode encoded_plantuml
diagram = ::Kramdown::PlantUml::Diagram.new(plantuml, options)
diagram.convert_to_svg
end

def logger
@logger ||= ::Kramdown::PlantUml::LogWrapper.init
end
end
end
end
67 changes: 10 additions & 57 deletions lib/kramdown-plantuml/jekyll_provider.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
# frozen_string_literal: true

require 'json'
require 'English'
require 'htmlentities'
require_relative 'log_wrapper'
require_relative 'diagram'
require_relative 'jekyll_page_processor'

module Kramdown
module PlantUml
Expand Down Expand Up @@ -32,20 +29,7 @@ def installed?
end

def needle(plantuml, options)
hash = { 'plantuml' => plantuml, 'options' => options.to_h }

<<~NEEDLE
<!--#kramdown-plantuml.start#-->
#{hash.to_json}
<!--#kramdown-plantuml.end#-->
NEEDLE
rescue StandardError => e
raise e if options.raise_errors?

puts e
logger.error 'Error while placing needle.'
logger.error e.to_s
logger.debug_multiline plantuml
JekyllPageProcessor.needle(plantuml, options)
end

private
Expand All @@ -63,54 +47,23 @@ def find_site_destination_dir

def register_hook
Jekyll::Hooks.register :site, :post_write do |site|
logger.debug ':site:post_write triggered.'

@site_destination_dir ||= site.dest

site.pages.each do |page|
page.output = replace_needles(page)
page.write(@site_destination_dir)
end
site_post_write(site)
end
end

def replace_needles(page)
logger.debug "Replacing Jekyll needle in #{page.path}"

html = page.output
return html if html.nil? || html.empty? || !html.is_a?(String)
def site_post_write(site)
logger.debug 'Jekyll:site:post_write triggered.'
@site_destination_dir ||= site.dest

html.gsub(/<!--#kramdown-plantuml\.start#-->(?<json>.*?)<!--#kramdown-plantuml\.end#-->/m) do
json = $LAST_MATCH_INFO[:json]
return replace_needle(json)
end
end
site.pages.each do |page|
processor = JekyllPageProcessor.new(page)

def replace_needle(json)
logger.debug 'Replacing Jekyll needle.'
next unless processor.should_process?

needle_hash = JSON.parse(json)
options_hash = needle_hash['options']
options = ::Kramdown::PlantUml::Options.new({ plantuml: options_hash })

begin
decode_and_convert(needle_hash, options)
rescue StandardError => e
raise e if options.raise_errors?

logger.error 'Error while replacing Jekyll needle.'
logger.error e.to_s
logger.debug_multiline json
processor.process(site.dest)
end
end

def decode_and_convert(hash, options)
encoded_plantuml = hash['plantuml']
plantuml = HTMLEntities.new.decode encoded_plantuml
diagram = ::Kramdown::PlantUml::Diagram.new(plantuml, options)
diagram.convert_to_svg
end

def load_jekyll
require 'jekyll'
::Jekyll
Expand Down
99 changes: 99 additions & 0 deletions spec/jekyll_page_processor_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# frozen_string_literal: true

require 'rspec/its'
require 'kramdown-plantuml/options'
require 'kramdown-plantuml/jekyll_page_processor'

Options = Kramdown::PlantUml::Options
JekyllPageProcessor = ::Kramdown::PlantUml::JekyllPageProcessor

describe JekyllPageProcessor do
let(:page) do
page = double('page')
allow(page).to receive(:output).and_return(output)
allow(page).to receive(:output=)
allow(page).to receive(:output_ext).and_return(output_ext)
allow(page).to receive(:data).and_return({})
allow(page).to receive(:write)
allow(page).to receive(:path).and_return(File.join(__dir__, 'page.md'))
page
end

subject { JekyllPageProcessor.new(page) }

describe '#initialize' do
context 'when page is nil' do
let(:page) { nil }
it { expect { subject }.to raise_error(ArgumentError, 'page cannot be nil') }
end
end

describe '#needle' do
subject { JekyllPageProcessor.needle(plantuml, options) }

context 'with nil :options' do
let(:options) { nil }
let(:plantuml) { "@startuml\n@enduml" }

it do
is_expected.to eq <<~NEEDLE
<!--#kramdown-plantuml.start#-->
{"plantuml":"@startuml\\n@enduml","options":{}}
<!--#kramdown-plantuml.end#-->
NEEDLE
end
end

context 'with nil :plantuml' do
let(:options) { Options.new }
let(:plantuml) { nil }

it do
is_expected.to eq <<~NEEDLE
<!--#kramdown-plantuml.start#-->
{"plantuml":null,"options":{}}
<!--#kramdown-plantuml.end#-->
NEEDLE
end
end

context 'with valid :options and :plantuml' do
let(:options) { { theme: { name: 'custom' } } }
let(:plantuml) { "@startuml\n@enduml" }

it do
is_expected.to eq <<~NEEDLE
<!--#kramdown-plantuml.start#-->
{"plantuml":"@startuml\\n@enduml","options":{"theme":{"name":"custom"}}}
<!--#kramdown-plantuml.end#-->
NEEDLE
end
end
end

describe '#process' do
before { subject.process(__dir__) }

context 'with HTML output' do
let(:output) { '<h1 id="hello">Hello</h1>' }
let(:output_ext) { '.html' }
its(:should_process?) { is_expected.to eq false }
it { expect(page.output).to eq output }
end
end

describe '#should_process?' do
context 'with HTML output' do
let(:output) { '<h1 id="hello">Hello</h1>' }
let(:output_ext) { '.html' }
its(:should_process?) { is_expected.to eq true }
it { expect(page.output).to eq output }
end

context 'with CSS output' do
let(:output) { 'body { display: none }' }
let(:output_ext) { '.css' }
its(:should_process?) { is_expected.to eq false }
end
end
end
3 changes: 2 additions & 1 deletion spec/jekyll_provider_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
'config' => File.join(jekyll_source, '_config.yml'),
'incremental' => false,
'source' => jekyll_source,
'verbose' => false,
'verbose' => ENV.fetch('DEBUG', false),
'destination' => jekyll_destination
})
end
Expand All @@ -60,6 +60,7 @@

context 'when plantuml contains HTML entities', :jekyll do
it { is_expected.to match(/<div class="plantuml"><svg.*<\/svg><\/div>/m) }
it { is_expected.to match(/<h1.*>This is a fixture<\/h1>/m) }
end
end
end
Expand Down

0 comments on commit e56aac7

Please sign in to comment.