def test_rel(self): actual = md.convert(u'[[sameAs::heyyou]]') expected = u'<p><a class="wikipage" href="/heyyou" itemprop="sameAs">' \ u'heyyou</a></p>' self.assertEqual(expected, actual) actual = md.convert(u'[[birthDate::1979-03-05 BCE]]') expected = u'<p><time datetime="1979-03-05 BCE" itemprop="birthDate">' \ u'<a class="wikipage" href="/1979_BCE">1979</a>' \ u'<span>-</span>' \ u'<a class="wikipage" href="/March_5">03-05</a>' \ u'<span> BCE</span></time></p>' self.assertEqual(expected, actual)
def validate_new_content(self, base_revision, new_body, user): # check metadata new_md = PageOperationMixin.parse_metadata(new_body) ## prevent self-revoke acl_r = new_md.get('read', '') acl_r = acl_r.split(',') if acl_r else [] acl_w = new_md.get('write', '') acl_w = acl_w.split(',') if acl_w else [] if not self.can_read(user, acl_r=acl_r, acl_w=acl_w): raise ValueError('Cannot restrict your permission') if not self.can_write(user, acl_r=acl_r, acl_w=acl_w): raise ValueError('Cannot restrict your permission') ## prevent circular-redirection try: WikiPage._follow_redirect(self, new_md.get(u'redirect')) except ValueError as e: raise e # check data new_data = PageOperationMixin.parse_data(self.title, new_body, new_md['schema']) if any(type(value) == schema.InvalidProperty for value in new_data.values()): raise ValueError('Invalid schema data') # check revision if self.revision < base_revision: raise ValueError('Invalid revision number: %d' % base_revision) # check headings if not TocGenerator(md.convert(new_body)).validate(): raise ValueError("Duplicate paths not allowed") return new_data, new_md
def test_isbn(self): actual = md.convert(u"{{isbn::0618680004}}") expected = ( u'<p><a class="isbn" href="http://www.amazon.com/gp/' u'product/0618680004" itemprop="isbn">0618680004</a></p>' ) self.assertEqual(expected, actual)
def test_url(self): actuals = [ u'http://x.co', u'(http://x.co)', u'http://x.co에', u'http://x.co?y', u'codeRepository::http://x.co', u'*****@*****.**', u'[email protected]에', u'http://www.youtube.com/watch?v=w5gmK-ZXIMQ', u'http://vimeo.com/1747316', ] expecteds = [ u'<p><a class="plainurl" href="http://x.co">http://x.co</a></p>', u'<p>(<a class="plainurl" href="http://x.co">http://x.co</a>)</p>', u'<p><a class="plainurl" href="http://x.co">http://x.co</a>에</p>', u'<p><a class="plainurl" href="http://x.co?y">http://x.co?y</a></p>', u'<p><a class="plainurl" href="http://x.co" ' u'itemprop="codeRepository">http://x.co</a></p>', u'<p><a class="email" href="mailto:[email protected]">[email protected]</a></p>', u'<p><a class="email" href="mailto:[email protected]">[email protected]</a>에</p>', u'<p>\n<div class="video youtube">\n<iframe allowfullscreen="true" frameborder="0" height="390" src="http://www.youtube.com/embed/w5gmK-ZXIMQ" width="640"></iframe>\n</div>\n</p>', u'<p>\n<div class="video vimeo">\n<iframe allowfullscreen="true" frameborder="0" height="281" src="http://player.vimeo.com/video/1747316" width="500"></iframe>\n</div>\n</p>', ] for e, a in zip(expecteds, actuals): self.assertEqual(e, md.convert(a))
def test_yyyymmdd_bce(self): actual = md.convert(u'[[1979-03-05 BCE]]') expected = u'<p><time datetime="1979-03-05 BCE">' \ u'<a class="wikipage" href="/1979_BCE">1979</a>' \ u'<span>-</span>' \ u'<a class="wikipage" href="/March_5">03-05</a>' \ u'<span> BCE</span></time></p>' self.assertEqual(expected, actual)
def test_yyyyxxxx(self): actual = md.convert(u'[[1979-??-??]]') expected = u'<p><time datetime="1979-??-??">' \ u'<a class="wikipage" href="/1979">1979</a>' \ u'<span>-</span>' \ u'<span>??-??</span>' \ u'</time></p>' self.assertEqual(expected, actual)
def test_isbn_kr(self): actual = md.convert(u"{{isbn::8936437267}}") expected = ( u'<p><a class="isbn" href="http://www.aladin.co.kr/' u"shop/wproduct.aspx?ISBN=" u'8936437267" itemprop="isbn">8936437267</a></p>' ) self.assertEqual(expected, actual)
def test_yyyymmxx(self): actual = md.convert(u"[[1979-03-??]]") expected = ( u'<p><time datetime="1979-03-??">' u'<a class="wikipage" href="/1979">1979</a>' u"<span>-</span>" u'<a class="wikipage" href="/March">03-??</a>' u"</time></p>" ) self.assertEqual(expected, actual)
def render_body( cls, title, body, rendered_data="", inlinks={}, related_links_by_score={}, older_title=None, newer_title=None ): # body body_parts = [cls.remove_metadata(body)] # incoming links if len(inlinks) > 0: lines = [u"# Incoming Links"] for i, (rel, links) in enumerate(inlinks.items()): itemtype, rel = rel.split("/") lines.append( u'## %s <span class="hidden">(%s %d)</span>' % (schema.humane_property(itemtype, rel, True), itemtype, i) ) # remove dups and sort links = list(set(links)) links.sort() lines += [u"* [[%s]]" % t for t in links] body_parts.append(u"\n".join(lines)) # related links related_links = related_links_by_score if len(related_links) > 0: lines = [u"# Suggested Pages"] lines += [u"* {{.score::%.3f}} [[%s]]\n{.noli}" % (score, t) for t, score in related_links.items()[:10]] body_parts.append(u"\n".join(lines)) body_parts.append(u"* [More suggestions...](/+%s)\n{.more-suggestions}" % (cls.title_to_path(title))) # other posts if older_title or newer_title: lines = [u"# Other Posts"] if newer_title: lines.append(u"* {{.newer::newer}} [[%s]]\n{.noli}" % newer_title) if older_title: lines.append(u"* {{.older::older}} [[%s]]\n{.noli}" % older_title) body_parts.append(u"\n".join(lines)) # remove yaml/schema block joined = u"\n".join(body_parts) joined = re.sub(PageOperationMixin.re_yaml_schema, u"\n", joined) # render to html rendered = md.convert(joined) # add table of contents rendered = TocGenerator(rendered).add_toc() # add class for embedded image rendered = PageOperationMixin.re_img.sub(ur'<\1 class="img-container"><img\2/></\3>', rendered) # add structured data block rendered = rendered_data + rendered return cls.sanitize_html(rendered)
def render_body(cls, title, body, rendered_data='', inlinks={}, related_links_by_score={}, older_title=None, newer_title=None): # body body_parts = [cls.remove_metadata(body)] # incoming links if len(inlinks) > 0: lines = [u'# Incoming Links'] for i, (rel, links) in enumerate(inlinks.items()): itemtype, rel = rel.split('/') lines.append(u'## %s <span class="hidden">(%s %d)</span>' % (schema.humane_property(itemtype, rel, True), itemtype, i)) # remove dups and sort links = list(set(links)) links.sort() lines += [u'* [[%s]]' % t for t in links] body_parts.append(u'\n'.join(lines)) # related links related_links = related_links_by_score if len(related_links) > 0: lines = [u'# Suggested Pages'] lines += [u'* {{.score::%.3f}} [[%s]]\n{.noli}' % (score, t) for t, score in related_links.items()[:10]] body_parts.append(u'\n'.join(lines)) body_parts.append(u'* [More suggestions...](/+%s)\n{.more-suggestions}' % (cls.title_to_path(title))) # other posts if older_title or newer_title: lines = [u'# Other Posts'] if newer_title: lines.append(u'* {{.newer::newer}} [[%s]]\n{.noli}' % newer_title) if older_title: lines.append(u'* {{.older::older}} [[%s]]\n{.noli}' % older_title) body_parts.append(u'\n'.join(lines)) # remove yaml/schema block joined = u'\n'.join(body_parts) joined = re.sub(PageOperationMixin.re_yaml_schema, u'\n', joined) # render to html rendered = md.convert(joined) # add table of contents rendered = TocGenerator(rendered).add_toc() # add class for embedded image rendered = PageOperationMixin.re_img.sub(ur'<\1 class="img-container"><img\2/></\3>', rendered) # add structured data block rendered = rendered_data + rendered return cls.sanitize_html(rendered)
def render_body(cls, body, rendered_data='', inlinks={}, related_links_by_score={}, older_title=None, newer_title=None): # body body_parts = [cls.remove_metadata(body)] # incoming links if len(inlinks) > 0: lines = [u'# Incoming Links'] for rel, links in inlinks.items(): itemtype, rel = rel.split('/') lines.append(u'## %s' % schema.humane_property(itemtype, rel, True)) # remove dups and sort links = list(set(links)) links.sort() lines += [u'* [[%s]]' % title for title in links] body_parts.append(u'\n'.join(lines)) # related links related_links = related_links_by_score if len(related_links) > 0: lines = [u'# Suggested Pages'] lines += [u'* {{.score::%.3f}} [[%s]]\n{.noli}' % (score, title) for title, score in related_links.items()[:10]] body_parts.append(u'\n'.join(lines)) # other posts if older_title or newer_title: lines = [u'# Other Posts'] if newer_title: lines.append(u'* {{.newer::newer}} [[%s]]\n{.noli}' % newer_title) if older_title: lines.append(u'* {{.older::older}} [[%s]]\n{.noli}' % older_title) body_parts.append(u'\n'.join(lines)) # remove yaml/schema block joined = u'\n'.join(body_parts) joined = re.sub(PageOperationMixin.re_yaml_schema, u'\n', joined) # render to html rendered = md.convert(joined) # add table of contents rendered = TocGenerator(rendered).add_toc() # add class for embedded image rendered = PageOperationMixin.re_img.sub(ur'<\1 class="img-container"><img\2/></\3>', rendered) # add structured data block rendered = rendered_data + rendered return cls.sanitize_html(rendered)
def validate_new_content(self, base_revision, new_body, user): # check metadata new_md = PageOperationMixin.parse_metadata(new_body) ## prevent self-revoke acl_r = new_md.get('read', '') acl_r = acl_r.split(',') if acl_r else [] acl_w = new_md.get('write', '') acl_w = acl_w.split(',') if acl_w else [] if not self.can_read(user, acl_r=acl_r, acl_w=acl_w): raise ValueError('Cannot restrict your permission') if not self.can_write(user, acl_r=acl_r, acl_w=acl_w): raise ValueError('Cannot restrict your permission') ## prevent circular-redirection try: WikiPage._follow_redirect(self, new_md.get(u'redirect')) except ValueError as e: raise e # check data new_data = PageOperationMixin.parse_data(self.title, new_body, new_md['schema']) if any( type(value) == schema.InvalidProperty for value in new_data.values()): invalid_keys = [ key for key, value in new_data.iteritems() if type(value) == schema.InvalidProperty ] raise ValueError('Invalid schema data: %s' % ', '.join(invalid_keys)) # check revision if self.revision < base_revision: raise ValueError('Invalid revision number: %d' % base_revision) # check headings invalid_reason = TocGenerator(md.convert(new_body)).is_invalid() if invalid_reason: raise ValueError(invalid_reason) return new_data, new_md
def test_url(self): actuals = [ u"http://x.co", u"(http://x.co)", u"http://x.co에", u"http://x.co?y", u"codeRepository::http://x.co", u"*****@*****.**", u"[email protected]에", ] expecteds = [ u'<p><a class="plainurl" href="http://x.co">http://x.co</a></p>', u'<p>(<a class="plainurl" href="http://x.co">http://x.co</a>)</p>', u'<p><a class="plainurl" href="http://x.co">http://x.co</a>에</p>', u'<p><a class="plainurl" href="http://x.co?y">http://x.co?y</a></p>', u'<p><a class="plainurl" href="http://x.co" ' u'itemprop="codeRepository">http://x.co</a></p>', u'<p><a class="email" href="mailto:[email protected]">[email protected]</a></p>', u'<p><a class="email" href="mailto:[email protected]">[email protected]</a>에</p>', ] for e, a in zip(expecteds, actuals): self.assertEqual(e, md.convert(a))
def test_possible_conflict_with_plain_link(self): actual = md.convert(u'[[Hello]](there)') expected = u'<p><a class="wikipage" href="/Hello">Hello</a>(there)</p>' self.assertEqual(expected, actual)
def test_unicode_character(self): actual = md.convert(u'[[가]]') expected = u'<p><a class="wikipage" href="/%EA%B0%80">가</a></p>' self.assertEqual(expected, actual)
def test_special_character(self): actual = md.convert(u'[[You&I]]') expected = u'<p><a class="wikipage" href="/You%26I">You&I</a></p>' self.assertEqual(expected, actual)
def test_div(self): actual = md.convert(u'<div class="test">He*l*lo</div>\nWo*r*ld') expected = u'<div class="test">He*l*lo</div>\n\n<p>Wo<em>r</em>ld</p>' self.assertEqual(expected, actual)
def test_strikethrough(self): actual = md.convert(u'Hello ~~AK~~?') expected = u'<p>Hello <strike>AK</strike>?</p>' self.assertEqual(expected, actual)
def test_generic_key_value(self): actual = md.convert(u'{{hello::world from ak}}') expected = u'<p><span itemprop="hello">world from ak</span></p>' self.assertEqual(expected, actual)
def test_isbn13_kr(self): actual = md.convert(u'{{isbn::9788936437267}}') expected = u'<p><a class="isbn" href="http://www.aladin.co.kr/' \ u'shop/wproduct.aspx?ISBN=' \ u'9788936437267" itemprop="isbn">9788936437267</a></p>' self.assertEqual(expected, actual)
def test_plain(self): actual = md.convert(u'[[heyyou]]') expected = u'<p><a class="wikipage" href="/heyyou">heyyou</a></p>' self.assertEqual(expected, actual)
def test_class(self): actual = md.convert(u'{{.hello::world from ak}}') expected = u'<p><span class="hello">world from ak</span></p>' self.assertEqual(expected, actual)
def test_space(self): actual = md.convert(u'[[Hey you]]') expected = u'<p><a class="wikipage" href="/Hey_you">Hey you</a></p>' self.assertEqual(expected, actual)