diff --git a/README.adoc b/README.adoc
index 8e9ad5e..43ae786 100644
--- a/README.adoc
+++ b/README.adoc
@@ -101,6 +101,28 @@ The script will automatically create the output file [path]_sample.adoc_, replac
The converter is not perfect yet, but we'll get there with your help.
You'll can find a list of tasks that need attention listed in the WORKLOG.adoc file.
+=== Conditional attribute
+
+The DocBook conditional attribute "condition" is replaced to "ifdef" macro.
+
+Take note the marco is on a line by itself.
+
+For example, in the case of there is the DocBook inline element with condition.
+
+ abc
+
+It is converted to below AsciiDoc format.
+
+ a
+ ifdef::foo[]
+ b
+ endif::foo[]
+ c
+
+When it is converted to html format, the output is displayed with both a space before "b" and a space after "b".
+
+ a b c
+
== About this Project
=== Authors
diff --git a/lib/docbookrx.rb b/lib/docbookrx.rb
index bc0c611..b6635ec 100644
--- a/lib/docbookrx.rb
+++ b/lib/docbookrx.rb
@@ -7,6 +7,7 @@ def self.convert str, opts = {}
raise 'Not a parseable document' unless (root = xmldoc.root)
visitor = DocbookVisitor.new opts
root.accept visitor
+ visitor.after
visitor.lines * "\n"
end
diff --git a/lib/docbookrx/docbook_visitor.rb b/lib/docbookrx/docbook_visitor.rb
index c45a105..a48f59e 100644
--- a/lib/docbookrx/docbook_visitor.rb
+++ b/lib/docbookrx/docbook_visitor.rb
@@ -71,6 +71,8 @@ class DocbookVisitor
UI_NAMES = ['guibutton', 'guilabel', 'menuchoice', 'guimenu', 'keycap']
+ IGNORED_NAMES = ['title', 'subtitle', 'toc']
+
attr_reader :lines
def initialize opts = {}
@@ -143,6 +145,10 @@ def visit node
after_traverse node, visit_method_name if (respond_to? :after_traverse)
end
+ def after
+ replace_ifdef_lines
+ end
+
def traverse_children node, opts = {}
(opts[:using_elements] ? node.elements : node.children).each do |child|
child.accept self
@@ -291,6 +297,10 @@ def append_text text, unsub = false
## Lifecycle callbacks
def before_traverse node, method
+ unless IGNORED_NAMES.include? node.name
+ append_ifdef_start_if_condition(node)
+ end
+
case method.to_s
when "visit_itemizedlist", "visit_orderedlist"
@list_depth += 1
@@ -336,6 +346,10 @@ def after_traverse node, method
end
end
end
+
+ unless IGNORED_NAMES.include? node.name
+ append_ifdef_end_if_condition(node)
+ end
end
## Node visitor callbacks
@@ -355,10 +369,10 @@ def ignore node
false
end
# Skip title and subtitle as they're always handled by the parent visitor
- alias :visit_title :ignore
- alias :visit_subtitle :ignore
-
- alias :visit_toc :ignore
+ IGNORED_NAMES.each do |name|
+ method_name = "visit_#{name}".to_sym
+ alias_method method_name, :ignore
+ end
### Document node (article | book | chapter) & header node (articleinfo | bookinfo | info) visitors
@@ -497,7 +511,9 @@ def process_section node, special = nil
append_blank_line
append_line %([#{special}])
end
- title = if (title_node = (node.at_css '> title') || (node.at_css '> info > title'))
+
+ title_node = (node.at_css '> title') || (node.at_css '> info > title')
+ title = if title_node
if (subtitle_node = (node.at_css '> subtitle') || (node.at_css '> info > subtitle'))
title_node.inner_html += %(: #{subtitle_node.inner_html})
end
@@ -514,8 +530,10 @@ def process_section node, special = nil
if (id = (resolve_id node, normalize: @normalize_ids)) && id != (generate_id title)
append_line %([[#{id}]])
end
+ append_ifdef_start_if_condition(title_node) if title_node
append_line %(#{'=' * @level} #{unwrap_text title})
lines.concat(text) unless text.nil? || text.empty?
+ append_ifdef_end_if_condition(title_node) if title_node
yield if block_given?
if (abstract_node = (node.at_css '> info > abstract'))
append_line
@@ -1035,6 +1053,7 @@ def process_table node
append_blank_line
end
(node.css '> tgroup > tbody > row').each do |row|
+ append_ifdef_start_if_condition(row)
append_blank_line
row.elements.each do |cell|
case cell.name
@@ -1045,6 +1064,7 @@ def process_table node
proceed cell
end
end
+ append_ifdef_end_if_condition(row)
end
if foot
(foot.css '> row > entry').each do |cell|
@@ -1563,5 +1583,42 @@ def lazy_quote text, seek = ','
def unwrap_text text
text.gsub WrappedIndentRx, ''
end
+
+ def element_with_condition? node
+ node.type == ELEMENT_NODE && node.attr('condition')
+ end
+
+ def append_ifdef_if_condition node
+ return unless element_with_condition?(node)
+ condition = node.attr('condition')
+ yield condition
+ end
+
+ def append_ifdef_start_if_condition node
+ append_ifdef_if_condition node do |condition|
+ append_line "ifdef::#{condition}[]"
+ end
+ end
+
+ def append_ifdef_end_if_condition node
+ append_ifdef_if_condition node do |condition|
+ append_line "endif::#{condition}[]"
+ end
+ end
+
+ def replace_ifdef_lines
+ out_lines = []
+ @lines.each do |line|
+ if (data = line.match(/^((ifdef|endif)::.+?\[\])(.+)$/))
+ # data[1]: "(ifdef|endif)::someting[]"
+ out_lines << data[1]
+ # data[3]: a string after "[]"
+ out_lines << data[3]
+ else
+ out_lines << line
+ end
+ end
+ @lines = out_lines
+ end
end
end
diff --git a/spec/lib/docbookrx/docbookrx_spec.rb b/spec/lib/docbookrx/docbookrx_spec.rb
index f7f54cf..80d4b47 100644
--- a/spec/lib/docbookrx/docbookrx_spec.rb
+++ b/spec/lib/docbookrx/docbookrx_spec.rb
@@ -987,4 +987,417 @@
expect(output).to include(expected)
end
+
+ describe "of node with condition" do
+ ['phrase', 'foreignphrase', 'guiicon'].each do |name|
+ describe "for inline #{name}" do
+ it 'should convert from no condition' do
+ input = <<-EOS
+a<#{name}>b#{name}>c
+ EOS
+ expected = <<-EOS.rstrip
+
+ab
+c
+ EOS
+ output = Docbookrx.convert input
+ expect(output).to eq(expected)
+ end
+
+ it 'should convert to ifdef directive' do
+ input = <<-EOS
+a<#{name} condition="foo">b#{name}>c
+ EOS
+ expected = <<-EOS.rstrip
+
+a
+ifdef::foo[]
+b
+endif::foo[]
+c
+ EOS
+ output = Docbookrx.convert input
+ expect(output).to eq(expected)
+ end
+
+ it 'should convert from new line tag to ifdef directive.' do
+ input = <<-EOS
+a
+<#{name} condition="foo">b#{name}>
+c
+ EOS
+ expected = <<-EOS.rstrip
+
+a
+ifdef::foo[]
+b
+endif::foo[]
+ c
+ EOS
+ output = Docbookrx.convert input
+ expect(output).to eq(expected)
+ end
+
+ it 'should convert to ifdef directives' do
+ input = <<-EOS
+a<#{name} condition="foo">b#{name}><#{name} condition="bar">c#{name}>d
+ EOS
+ expected = <<-EOS.rstrip
+
+a
+ifdef::foo[]
+b
+endif::foo[]
+ifdef::bar[]
+c
+endif::bar[]
+d
+ EOS
+ output = Docbookrx.convert input
+ expect(output).to eq(expected)
+ end
+ end
+ end
+
+ ['para', 'simpara'].each do |name|
+ describe "for block #{name}" do
+ it 'should convert from no condition' do
+ input = <<-EOS
+
+ <#{name}>a#{name}>
+ <#{name}>b#{name}>
+
+ EOS
+ expected = <<-EOS.rstrip
+
+
+a
+
+b
+ EOS
+ output = Docbookrx.convert input
+ expect(output).to eq(expected)
+ end
+
+ it 'should convert to ifdef directive' do
+ input = <<-EOS
+
+ <#{name} condition="foo">a#{name}>
+ <#{name} condition="bar">b#{name}>
+
+ EOS
+ expected = <<-EOS.rstrip
+
+
+ifdef::foo[]
+
+a
+endif::foo[]
+ifdef::bar[]
+
+b
+endif::bar[]
+ EOS
+ output = Docbookrx.convert input
+ expect(output).to eq(expected)
+ end
+ end
+ end
+
+ describe "for block table, row" do
+ it 'should convert from no condition' do
+ input = <<-EOS
+
+
+ a1
+
+
+
+
+
+ a2
+
+
+
+
+
+
+ a3
+
+
+
+
+
+
+
+ EOS
+ expected = <<-EOS.rstrip
+
+
+
+.a1
+[cols="1"]
+|===
+|
+
+a2
+
+|
+
+a3
+|===
+
+ EOS
+ output = Docbookrx.convert input
+ expect(output).to eq(expected)
+ end
+
+ it 'should convert from table condition to ifdef directive' do
+ input = <<-EOS
+
+
+ a1
+
+
+
+
+
+ a2
+
+
+
+
+
+
+
+ EOS
+ expected = <<-EOS.rstrip
+
+
+ifdef::foo[]
+
+.a1
+[cols="1"]
+|===
+|
+
+a2
+|===
+endif::foo[]
+
+ EOS
+ output = Docbookrx.convert input
+ expect(output).to eq(expected)
+ end
+
+ it 'should convert from row condition to ifdef directive' do
+ input = <<-EOS
+
+
+ a1
+
+
+
+
+ a2
+
+
+
+
+ a3
+
+
+
+
+
+
+ EOS
+ expected = <<-EOS.rstrip
+
+
+
+.a1
+[cols="1"]
+|===
+ifdef::foo[]
+|
+
+a2
+endif::foo[]
+ifdef::bar[]
+
+|
+
+a3
+endif::bar[]
+|===
+
+ EOS
+ output = Docbookrx.convert input
+ expect(output).to eq(expected)
+
+ end
+ end
+
+ describe "for block figure" do
+ it 'should convert from no condition' do
+ input = <<-EOS
+
+
+
+
+ EOS
+ expected = <<-EOS
+
+
+
+.a1
+image::images/dummy.png[]
+
+
+.b1
+image::images/dummy2.png[]
+ EOS
+ output = Docbookrx.convert input
+ expect(output).to eq(expected)
+ end
+
+ it 'should convert to ifdef directive' do
+ input = <<-EOS
+
+
+
+
+ EOS
+ expected = <<-EOS
+
+
+ifdef::foo[]
+
+.a1
+image::images/dummy.png[]
+
+endif::foo[]
+
+.b1
+image::images/dummy2.png[]
+ EOS
+ output = Docbookrx.convert input
+ expect(output).to eq(expected)
+
+ end
+ end
+
+ describe "for meta title" do
+ it 'should convert from no condition' do
+ input = <<-EOS
+
+ EOS
+ expected = <<-EOS.rstrip
+
+= a
+ EOS
+ output = Docbookrx.convert input
+ expect(output).to eq(expected)
+ end
+
+ it 'should convert from condition to ifdef directive' do
+ input = <<-EOS
+
+ EOS
+ expected = <<-EOS.rstrip
+
+ifdef::foo[]
+= a
+endif::foo[]
+ EOS
+ output = Docbookrx.convert input
+ expect(output).to eq(expected)
+ end
+ end
+
+ describe "for other nodes" do
+ let(:root) do
+ xmldoc = ::Nokogiri::XML::Document.parse(input)
+ xmldoc.root
+ end
+ let(:visitor) do
+ Docbookrx::DocbookVisitor.new({})
+ end
+
+ [
+ { :name => 'note', :method => :process_admonition },
+ { :name => 'important', :method => :process_admonition },
+ { :name => 'warning', :method => :process_admonition },
+ { :name => 'application', :method => :process_literal },
+ { :name => 'classname', :method => :process_literal },
+ { :name => 'command', :method => :process_literal },
+ { :name => 'literal', :method => :process_literal },
+ { :name => 'citetitle', :method => :process_keyword },
+ { :name => 'filename', :method => :process_path },
+ { :name => 'guilabel', :method => :process_ui },
+ { :name => 'section', :method => :process_section },
+ { :name => 'bridgehead', :method => :visit_bridgehead },
+ { :name => 'example', :method => :visit_example },
+ { :name => 'itemizedlist', :method => :visit_itemizedlist },
+ { :name => 'listitem', :method => :visit_listitem },
+ { :name => 'procedure', :method => :visit_procedure },
+ { :name => 'programlisting', :method => :visit_programlisting },
+ { :name => 'screen', :method => :visit_screen },
+ { :name => 'step', :method => :visit_step },
+ { :name => 'ulink', :method => :visit_ulink },
+ { :name => 'varlistentry', :method => :visit_varlistentry },
+ { :name => 'xref', :method => :visit_xref },
+ ].each do |node_hash|
+ name = node_hash[:name]
+ describe name do
+ let(:input) do
+ <<-EOS
+
+ <#{name} condition="foo">dummy#{name}>
+
+ EOS
+ end
+
+ it "should convert to ifdef directive" do
+ allow(visitor).to receive(node_hash[:method]).and_return(false)
+ root.accept(visitor)
+ expect(visitor.lines.grep(/^ifdef/).length).to eq(1)
+ end
+ end
+ end
+ end
+ end
end