# -*- encoding : utf-8 -*- require "card/content" describe Card::Content do EXAMPLES = { nests: { content: "Some Literals: \\[{I'm not| a link]}, and " \ '\\{{This Card|Is not Nestd}}' \ ", but " \ "{{this is}}" \ ", and some tail", rendered: ["Some Literals: \\[{I'm not| a link]}, and ", "{{This Card|Is not Nestd}}", ", but ", { options: { nest_name: "this is", nest_syntax: "this is" } }, ", and some tail"], classes: [String, :EscapedLiteral, String, :Nest, String] }, links_and_nests: { content: "Some Links and includes: [[the card|the text]], " \ "and {{This Card|Is Nestd}}{{this too}} " \ "and [[http://external.wagn.org/path|link text]]" \ "{{Nestd|open}}", rendered: ["Some Links and includes: ", '' \ 'the text', ", and ", { options: { view: "Is Nestd", nest_name: "This Card", nest_syntax: "This Card|Is Nestd" } }, { options: { nest_name: "this too", nest_syntax: "this too" } }, " and ", 'link text', { options: { view: "open", nest_name: "Nestd", nest_syntax: "Nestd|open" } }], classes: [ String, :Link, String, :Nest, :Nest, String, :Link, :Nest ] }, uris_and_links: { content: "Some URIs and Links: http://a.url.com/ " \ "More urls: wagn.com/a/path/to.html " \ "http://localhost:2020/path?cgi=foo&bar=baz " \ "[[http://brain.org/Home|extra]] " \ "[ http://gerry.wagn.com/a/path ] " \ "{ https://brain.org/more?args } ", rendered: ["Some URIs and Links: ", 'http://a.url.com/', " More urls: ", '' \ "wagn.com/a/path/to.html", " ", '' \ "http://localhost:2020/path?cgi=foo&bar=baz", " ", 'extra', " [ ", '' \ "http://gerry.wagn.com/a/path", " ] { ", '' \ "https://brain.org/more?args", " } "], text_rendered: ["Some URIs and Links: ", "http://a.url.com/", " More urls: ", "wagn.com/a/path/to.html[http://wagn.com/a/path/to.html]", " ", "http://localhost:2020/path?cgi=foo&bar=baz", " ", "extra[http://brain.org/Home]", " [ ", "http://gerry.wagn.com/a/path", " ] { ", "https://brain.org/more?args", " } "], classes: [ String, :URI, String, :HostURI, String, :URI, String, :Link, String, :URI, String, :URI, String ] }, uris_and_links_2: { content: "Some URIs and Links: http://a.url.com " \ "More urls: wagn.com/a/path/to.html " \ "[ http://gerry.wagn.com/a/path ] " \ "{ https://brain.org/more?args } " \ "http://localhost:2020/path?cgi=foo&bar=baz " \ "[[http://brain.org/Home|extra]]", rendered: ["Some URIs and Links: ", 'http://a.url.com', " More urls: ", '' \ "wagn.com/a/path/to.html", " [ ", '' \ "http://gerry.wagn.com/a/path", " ] { ", '' \ "https://brain.org/more?args", " } ", '' \ "http://localhost:2020/path?cgi=foo&bar=baz", " ", 'extra'], classes: [ String, :URI, String, :HostURI, String, :URI, String, :URI, String, :URI, String, :Link ] }, no_chunks: { content: "No chunks", rendered: "No chunks" }, single_nest: { content: "{{one nest|size;large}}", classes: [:Nest] }, css: { content: %( /* body text */ body { color: #444444; } /* page - background image and color */ body#wagn { background: #ffffff; } /* top bar background color; text colors */ #menu { background: #3260a0; } #menu a { color: #EEEEEE; } /* header text */ h1, h2 { color: #664444; } h1.page-header, h2.page-header { color: #222299; } ) } }.freeze EXAMPLES.each_value do |val| next unless val[:classes] val[:classes] = val[:classes].map do |klass| klass.is_a?(Class) ? klass : Card::Content::Chunk.const_get(klass) end end context "instance" do before do @check_proc = proc do |m, v| if m.is_a? Array wrong_class = m[0] != v.class expect(wrong_class).to be_falsey is_last = m.size == 1 is_last ? true : m[1..-1] unless wrong_class end end assert card = Card["One"] @card = card # non-nil valued opts only ... @render_block = proc do |opts| options = opts.inject({}) do |i, v| i if !v[1].nil? && (i[v[0]] = v[1]) end { options: options } end end let(:example) { EXAMPLES[@example] } let(:cobj) { Card::Content.new example[:content], @card } let(:classes) { example[:classes] } let(:rendered) { example[:rendered] } let(:text_rendered) { example[:text_rendered] } let(:content) { example[:content] } describe "parse" do def check_chunk_classes all_classes_pass_check_proc clist = nonstring_classes cobj.each_chunk do |chk| expect(chk).to be_instance_of clist.shift end expect(clist).to be_empty end def nonstring_classes classes.select { |c| String != c } end def all_classes_pass_check_proc expect(cobj.inject(classes, &@check_proc)).to eq(true) end it "finds all the chunks and strings" do # note the mixed [} that are considered matching, needs some cleanup ... @example = :nests all_classes_pass_check_proc end it "gives just the chunks" do @example = :nests check_chunk_classes end it "finds all the chunks links and trasclusions" do @example = :links_and_nests all_classes_pass_check_proc end it "finds uri chunks " do # tried some tougher cases that failed, don't know the spec, so # hard to form better tests for URIs here @example = :uris_and_links check_chunk_classes end it "finds uri chunks (b)" do # tried some tougher cases that failed, don't know the spec, so # hard to form better tests for URIs here @example = :uris_and_links_2 check_chunk_classes end it "parses just a string" do @example = :no_chunks expect(cobj).to eq(rendered) end it "parses a single chunk" do @example = :single_nest check_chunk_classes end it "leaves css alone" do @example = :css expect(cobj).to eq(content) end end describe "render" do it "renders all nests" do @example = :nests expect(cobj.as_json.to_s).to match(/not rendered/) cobj.process_each_chunk(&@render_block) rdr = cobj.as_json.to_json expect(rdr).not_to match(/not rendered/) expect(rdr).to eq(rendered.to_json) end it "renders links and nests" do @example = :links_and_nests cobj.process_each_chunk(&@render_block) rdr = cobj.as_json.to_json expect(rdr).not_to match(/not rendered/) expect(rdr).to eq(rendered.to_json) end it "renders links correctly for text formatters" do @example = :uris_and_links card2 = Card[@card.id] format = card2.format format: :text cobj = Card::Content.new content, format cobj.process_each_chunk(&@render_block) expect(cobj.as_json.to_json).to eq(text_rendered.to_json) end it "does not need rendering if no nests" do @example = :uris_and_links cobj.process_each_chunk(&@render_block) expect(cobj.as_json.to_json).to eq(rendered.to_json) end it "does not need rendering if no nests (b)" do @example = :uris_and_links_2 rdr1 = cobj.as_json.to_json expect(rdr1).to match(/not rendered/) # links are rendered too, but not with a block cobj.process_each_chunk(&@render_block) rdr2 = cobj.as_json.to_json expect(rdr2).not_to match(/not rendered/) expect(rdr2).to eq(rendered.to_json) end end end UNTAGGED_CASES = [" [grrew][/wiki/grrew]ss ", " {{this is a test}}, {{this|view|is:too}} and", " so is http://foo.bar.come//", ' and foo="my attr, not int a tag" and more'].freeze context "class" do describe "#clean!" do it "does not alter untagged content" do UNTAGGED_CASES.each do |test_case| assert_equal test_case, Card::Content.clean!(test_case) end end it "strips disallowed html class attributes" do assert_equal "

html

with
funky tags

", Card::Content.clean!( '

html

with
' \ "funkytags

" ) assert_equal "foo", Card::Content.clean!('foo') end it "does not strip permitted_classes" do has_stripped1 = 'foo' assert_equal has_stripped1, Card::Content.clean!(has_stripped1) has_stripped2 = '

foo

' assert_equal has_stripped2, Card::Content.clean!(has_stripped2) end it "strips permitted_classes " \ "but not permitted ones when both are present" do assert_equal 'foo', Card::Content.clean!( 'foo' ) assert_equal '

foo

', Card::Content.clean!( '

foo

' ) assert_equal '

foo

', Card::Content.clean!( '

foo

' ) end it "allows permitted attributes" do assert_equal '', Card::Content.clean!('') assert_equal "foo", Card::Content.clean!("foo") assert_equal '', Card::Content.clean!("") assert_equal '', Card::Content.clean!('') assert_equal '', Card::Content.clean!('') assert_equal '
', Card::Content.clean!('
') end it "does not allow nonpermitted attributes" do assert_equal "", Card::Content.clean!('') assert_equal "

", Card::Content.clean!('

') end it "removes comments" do assert_equal "yo", Card::Content.clean!("yo") assert_equal "joe", Card::Content.clean!("joe") end it "fixes regular nbsp order by default" do assert_equal "space  test  two   space", Card::Content.clean!( "space  test  two   space" ) end # it "doesn't fix regular nbsp order with setting" do # # manually configure this setting, then make this one live # # (test above will then fail) # pending "Can't set Card.config.space_last_in_multispace= false "\ # 'for one test' # assert_equal 'space  test  two   space', # Card::Content.clean!( # 'space  test  two   space' # ) # end end end describe "#pieces" do def pieces content Card::Content.new(content, Card["A"],).pieces end example "A {{B}}" do expect(pieces("A {{B}}").size).to eq 2 end example "A" do expect(pieces("A").size).to eq 1 end example "{{B}}" do expect(pieces("{{B}}").size).to eq 1 end end end