Personal wiki notebook (not under development)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Node.py 2.5KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. class Node( object ):
  2. """
  3. An HTML node, consisting of an opening and closing HTML tag, potentially with stuff in between
  4. and attributes on the opening tag.
  5. """
  6. tag = None # the name of the HTML tag to use for this node
  7. def __init__( self, *children, **attrs ):
  8. self.__attrs = attrs
  9. self.__children = []
  10. if "separator" in attrs:
  11. self.__separator = attrs[ "separator" ]
  12. del( attrs[ "separator" ] )
  13. else:
  14. self.__separator = u"\n"
  15. if "prefix" in attrs:
  16. self.__prefix = attrs[ "prefix" ]
  17. del( attrs[ "prefix" ] )
  18. else:
  19. self.__prefix = u""
  20. # flatten any lists contained within the children list.
  21. # so [ [ a, b ], [ c, d ] ] becomes just [ a, b, c, d ]
  22. for child in children:
  23. if child is None: continue
  24. if type( child ) == list:
  25. self.__children.extend( child )
  26. else:
  27. self.__children.append( child )
  28. children = property( lambda self: self.__children )
  29. attrs = property( lambda self: self.__attrs )
  30. def __str__( self ):
  31. # render this node's children
  32. rendered_children = self.__separator.join( [ unicode( child ) for child in self.__children ] )
  33. # if there is no tag, just return the children by themself
  34. if self.tag is None:
  35. return self.__prefix + rendered_children
  36. # render attributes in the open tag
  37. if len( self.__attrs ) == 0:
  38. open_tag = u"<%s>" % self.tag
  39. else:
  40. rendered_attrs = u" ".join( [ '%s="%s"' % ( Node.transform_name( name ), value )
  41. for ( name, value ) in self.__attrs.items() if value is not None ] )
  42. open_tag = u"<%s %s>" % ( self.tag, rendered_attrs )
  43. close_tag = u"</%s>" % self.tag
  44. # return the rendered node
  45. if len( self.__children ) == 0:
  46. return self.__prefix + u"%s%s" % ( open_tag, close_tag )
  47. elif len( self.__children ) == 1 and len( rendered_children ) < 80:
  48. separator = u""
  49. else:
  50. separator = self.__separator
  51. return self.__prefix + separator.join( [ open_tag, rendered_children, close_tag ] )
  52. @staticmethod
  53. def transform_name( name ):
  54. # since u"class" is a Python keyword, allow u"class_" instead
  55. if name == u"class_":
  56. return u"class"
  57. if name.endswith( u"_dc" ):
  58. # since Python identifiers can't contain colons, replace underscores with colons
  59. return name.replace( u"_", u":" )
  60. else:
  61. # since Python identifiers can't contain dashes, replace underscores with dashes
  62. return name.replace( u"_", u"-" )