diff --git a/doc/format.md b/doc/format.md index 6095c897a..d5f83a9fc 100644 --- a/doc/format.md +++ b/doc/format.md @@ -688,7 +688,9 @@ Usage: ## Raw Data Block -When you want to write non-Re:VIEW line, use `//raw`. +When you want to write non-Re:VIEW line, use `//raw` or `//embed`. + +### `//raw` block Usage: @@ -715,6 +717,39 @@ this is a special line. Note: `//raw` and `@` may break structured document easily. +### `//embed` block + +Usage: + +``` +//embed{ +
+this is a special line. +
+//} + +//embed[html,markdown]{ +
+this is a special line. +
+//} +``` + +In above line, `html` and `markdown` is a builder name that handle raw data. + +Output: + +(In HTML:) + +``` +
+this is a special line. +
+``` + +(In other formats, it is just ignored.) + + ## Inline Commands ### Styles diff --git a/lib/review/builder.rb b/lib/review/builder.rb index 87cb05e62..72a46e8e5 100644 --- a/lib/review/builder.rb +++ b/lib/review/builder.rb @@ -344,6 +344,20 @@ def raw(str) end end + def embed(lines, arg = nil) + if arg + builders = arg.gsub(/^\s*\|/, "").gsub(/\|\s*$/, "").gsub(/\s/, "").split(/,/) + c = target_name + if builders.include?(c) + print lines.join() + else + "" + end + else + print lines.join() + end + end + def warn(msg) $stderr.puts "#{@location}: warning: #{msg}" end @@ -478,6 +492,19 @@ def inline_raw(args) end end + def inline_embed(args) + if matched = args.match(/\|(.*?)\|(.*)/) + builders = matched[1].split(/,/).map{|i| i.gsub(/\s/, '') } + if builders.include?(target_name) + matched[2] + else + "" + end + else + args + end + end + ## override TextUtils::detab def detab(str, num = nil) if num diff --git a/lib/review/compiler.rb b/lib/review/compiler.rb index 12ada7383..afde37aa6 100644 --- a/lib/review/compiler.rb +++ b/lib/review/compiler.rb @@ -161,6 +161,7 @@ def inline_defined?(name) defblock :tip, 0..1 defblock :box, 0..1 defblock :comment, 0..1, true + defblock :embed, 0..1 defsingle :footnote, 2 defsingle :noindent, 0 @@ -230,11 +231,12 @@ def inline_defined?(name) definline :comment definline :include definline :tcy + definline :embed private def do_compile - f = LineInput.new(Preprocessor::Strip.new(StringIO.new(@chapter.content))) + f = LineInput.new(StringIO.new(@chapter.content)) @strategy.bind self, @chapter, Location.new(@chapter.basename, f) tagged_section_init while f.next? @@ -266,7 +268,7 @@ def do_compile warn "`//' seen but is not valid command: #{line.strip.inspect}" if block_open?(line) warn "skipping block..." - read_block(f) + read_block(f, false) end else if f.peek.strip.empty? @@ -432,8 +434,9 @@ def compile_paragraph(f) def read_command(f) line = f.gets name = line.slice(/[a-z]+/).to_sym + ignore_inline = (name == :embed) args = parse_args(line.sub(%r<\A//[a-z]+>, '').rstrip.chomp('{'), name) - lines = block_open?(line) ? read_block(f) : nil + lines = block_open?(line) ? read_block(f, ignore_inline) : nil return name, args, lines end @@ -441,12 +444,16 @@ def block_open?(line) line.rstrip[-1,1] == '{' end - def read_block(f) + def read_block(f, ignore_inline) head = f.lineno buf = [] f.until_match(%r<\A//\}>) do |line| - unless line =~ /\A\#@/ - buf.push text(line.rstrip) + if ignore_inline + buf.push line + else + unless line =~ /\A\#@/ + buf.push text(line.rstrip) + end end end unless %r<\A//\}> =~ f.peek diff --git a/test/test_htmlbuilder.rb b/test/test_htmlbuilder.rb index cae4635a8..dbf953e08 100644 --- a/test/test_htmlbuilder.rb +++ b/test/test_htmlbuilder.rb @@ -1322,6 +1322,63 @@ def test_inline_raw5 assert_equal "nor\nmal", compile_inline("@{|html|nor\\nmal}") end + def test_inline_embed0 + assert_equal "normal", compile_inline("@{normal}") + end + + def test_inline_embed1 + assert_equal "body", compile_inline("@{|html|body}") + end + + def test_inline_embed3 + assert_equal "", compile_inline("@{|idgxml, latex|body}") + end + + def test_inline_embed5 + assert_equal 'nor\\nmal', compile_inline("@{|html|nor\\nmal}") + end + + def test_inline_embed_math1 + assert_equal '\[ \frac{\partial f}{\partial x} =x^2+xy \]', compile_inline('@{\[ \frac{\partial f\}{\partial x\} =x^2+xy \]}') + end + + def test_inline_embed_math1a + assert_equal '\[ \frac{\partial f}{\partial x} =x^2+xy \]', compile_inline('@{\\[ \\frac{\\partial f\}{\\partial x\} =x^2+xy \\]}') + end + + def test_inline_embed_math1b + assert_equal '\[ \frac{\partial f}{\partial x} =x^2+xy \]', compile_inline('@{\\\\[ \\\\frac{\\\\partial f\}{\\\\partial x\} =x^2+xy \\\\]}') + end + + def test_inline_embed_math1c + assert_equal '\\[ \\frac{}{} \\]', + compile_inline('@{\[ \\frac{\}{\} \\]}') + end + + def test_inline_embed_n1 + assert_equal '\\n', compile_inline('@{\\n}') + end + + def test_inline_embed_n2 + assert_equal '\\n', compile_inline('@{\\\\n}') + end + + def test_inline_embed_brace_right0 + assert_equal '}', compile_inline('@{\\}}') + end + + def test_inline_embed_brace_right1 + assert_equal '\\}', compile_inline('@{\\\\}}') + end + + def test_inline_embed_brace_right2 + assert_equal '\\}', compile_inline('@{\\\\\\}}') + end + + def test_inline_embed_brace_right3 + assert_equal '\\\\}', compile_inline('@{\\\\\\\\}}') + end + def test_block_raw0 actual = compile_block("//raw[<>!\"\\n& ]\n") expected = %Q(<>!\"\n& ) @@ -1352,6 +1409,48 @@ def test_block_raw4 assert_equal expected, actual end + def test_embed0 + lines = '//embed{' + "\n" + + ' <>!\\"\\\\n& ' + "\n" + + '//}' + "\n" + actual = compile_block(lines) + expected = ' <>!\\"\\\\n& ' + "\n" + assert_equal expected, actual + end + + def test_embed1 + actual = compile_block("//embed[|html|]{\n" + + "<>!\\\"\\\\n& \n" + + "//}\n") + expected = %Q(<>!\\\"\\\\n& \n) + assert_equal expected, actual + end + + def test_embed2 + actual = compile_block("//embed[html, latex]{\n" + + "<>!\\\"\\\\n& \n" + + "//}\n") + expected = %Q(<>!\\\"\\\\n& \n) + assert_equal expected, actual + end + + def test_embed2a + actual = compile_block("//embed[|html, latex|]{\n" + + "<>!\\\"\\\\n& \n" + + "//}\n") + expected = %Q(<>!\\\"\\\\n& \n) + assert_equal expected, actual + end + + def test_embed2b + actual = compile_block("//embed[html, latex]{\n" + + '#@# comments are not ignored in //embed block' + "\n" + + "<>!\\\"\\\\n& \n" + + "//}\n") + expected = '#@# comments are not ignored in //embed block' + "\n" + %Q(<>!\\\"\\\\n& \n) + assert_equal expected, actual + end + def test_inline_fn fn = Book::FootnoteIndex.parse(['//footnote[foo][bar\\a\\$buz]']) @chapter.instance_eval{@footnote_index=fn}