From 0b4e57b82c8a2ee87c59062017ea7c899de45522 Mon Sep 17 00:00:00 2001 From: byteface Date: Wed, 17 Jun 2020 22:54:48 +0100 Subject: [PATCH] updates --- README.md | 14 +- archive/bs5_test_carousel.html | 15 + bs5_test_dashboard.html | 15 + domonic/__init__.py | 99 +++--- domonic/dom.py | 577 +++++++++++++++++++++------------ domonic/html.py | 1 + domonic/javascript.py | 10 +- setup.py | 4 +- test_domonic.py | 468 +++++++++++++++++++++++++- 9 files changed, 940 insertions(+), 263 deletions(-) create mode 100644 archive/bs5_test_carousel.html create mode 100644 bs5_test_dashboard.html diff --git a/README.md b/README.md index 4dcf5dbb..e6c55eca 100755 --- a/README.md +++ b/README.md @@ -84,20 +84,24 @@ from html5print import HTMLBeautifier print(HTMLBeautifier.beautify(output, 4)) ``` -### common errors -If you incorrectly type the code it will obviously not work. So there are a bunch of common ones I've noticed : - -##### TODO - catch these and raise a friendly error that tells you what to fix +### Common Errors +If you incorrectly type code it will obviously not work. So there are a bunch of common ones I've noticed when creating large domonic templates. : IndexError: list index out of range - You most likely didn't put a underscore on an attribute. SyntaxError: invalid syntax - - You most likely are missing a comma somewhere between params + - You are Missing a comma between attributes SyntaxError: positional argument follows keyword argument - You have to pass attributes LAST. and strings and objects first. *see docs* +TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'dict' + - You are Missing a comma between attributes. before the **{} + +##### TODO - catch these and raise a friendly custom ParseError that tells you what to fix + + ### run tests ```bash diff --git a/archive/bs5_test_carousel.html b/archive/bs5_test_carousel.html new file mode 100644 index 00000000..b23bd94f --- /dev/null +++ b/archive/bs5_test_carousel.html @@ -0,0 +1,15 @@ +Carousel Template · Bootstrap
Carousel
  • Example headline.

    Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.

    Sign up today

    Another example headline.

    Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.

    Learn more

    One more for good measure.

    Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.

    Browse gallery

    PreviousNext140x140

    Heading

    Donec sed odio dui. Etiam porta sem malesuada magna mollis euismod. Nullam id dolor id nibh ultricies vehicula ut id elit. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Praesent commodo cursus magna.

    View details »

    140x140

    Heading

    Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Cras mattis consectetur purus sit amet fermentum. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh.

    View details »

    140x140

    Heading

    Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.

    View details »


    First featurette heading.It’ll blow your mind.

    Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis euismod semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus commodo.

    500x500

    Oh yeah, it’s that good.See for yourself.

    Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis euismod semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus commodo.

    500x500

    Checkmate.And lastly, this one.

    Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis euismod semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus commodo.

    500x500

    Back to top

    © 2017-2020 Company, Inc. ·Privacy·Terms

    \ No newline at end of file diff --git a/bs5_test_dashboard.html b/bs5_test_dashboard.html new file mode 100644 index 00000000..0e4d31ca --- /dev/null +++ b/bs5_test_dashboard.html @@ -0,0 +1,15 @@ +Dashboard Template · BootstrapCompany nameSaved reports

    Dashboard

    Section title

    #HeaderHeaderHeaderHeader1, 001Loremipsumdolorsit1, 002ametconsecteturadipiscingelit1, 003IntegernecodioPraesent1, 003liberoSedcursusante1, 004dapibusdiamSednisi1, 005Nullaquissemat1, 006nibhelementumimperdietDuis1, 007sagittisipsumPraesentmauris1, 008Fuscenectellussed1, 009auguesemperportaMauris1, 010massaVestibulumlaciniaarcu1, 011egetnullaClassaptent1, 012tacitisociosquadlitora1, 013torquentperconubianostra1, 014perinceptoshimenaeosCurabitur1, 015sodalesligula in libero \ No newline at end of file diff --git a/domonic/__init__.py b/domonic/__init__.py index 4b8feeb6..3c9db735 100755 --- a/domonic/__init__.py +++ b/domonic/__init__.py @@ -6,7 +6,7 @@ Generate HTML using python 3 """ -__version__ = "0.0.3" +__version__ = "0.0.4" from typing import * @@ -34,16 +34,10 @@ def print(domonic) -> str : @staticmethod def parse(html:str) -> str : - ''' HTML as input and returns domonic ''' + ''' HTML as input and returns python ''' print("attempting to parse the page") - # - TODO - should probs pretty it up first and strip want cant be - # turn all tags into class definitions. - # check closing tags. turn to closed bracks - # create strings around content and remove white space - # put underscores on attributes - import re html = ''.join(html.split('')) @@ -51,9 +45,7 @@ def parse(html:str) -> str : # html = "some content" - # "style","script" - - htmltags = ["html","span","button","link","form","nav","details","summary","header","head","body","meta","title","div","footer","img","a","p","h1","h2","h3","h4","h5","h6","hr","ul","ol","li","time","template","label","input","small","strong","option","select"] + htmltags = ["html","span","button","link","form","nav","details","summary","header","head","body","meta","title","div","footer","img","a","p","h1","h2","h3","h4","h5","h6","hr","ul","ol","li","time","template","label","input","small","strong","option","select","main","td","tr","thead","th","table","tbody","canvas","b","center","br"] for tag in htmltags: @@ -76,49 +68,78 @@ def parse(html:str) -> str : pattern = re.compile(reg) html = re.sub( pattern, ')', html)#, flags=re.IGNORECASE ) - # second pass. single no closed. i.e meta - # reg = f">" - # pattern = re.compile(reg) - # html = re.sub( pattern, ')', html)#, flags=re.IGNORECASE ) - - # need to get all the ( and ) - # count left and right. until it changes. - # left > (((() - # right > )(() - - - - # tags = re.findall(pattern,html) - # if len(tags) < 1: - # continue - # print(tags) - # for count,each in enumerate(tags): - # print(count,each) - # tags[count] = tag + "(" + each + ")" - # html = ''.join(tags) - # print(count, html) - - print(html) - # close any tags that arent properly self closing flag=False + increase_index=0 # by the amount of new chars you add for index,char in enumerate(html): - if char=="(":flag=True + index = index+increase_index + if char=="(": + flag=True + tag = html[index-4] + html[index-3] + html[index-2] + html[index-1] + print(tag) + if char==")":flag=False if char==">" and flag is True: - html = f"{html[:index]},{html[index+1:]}" # replace it for a ',' - # TODO - if its self closing. replace for a ')' instead + if 'meta' in tag or 'link' in tag or 'hr' in tag: + html = f"{html[:index]}),{html[index+1:]}" # replace it for a '),' + increase_index +=1 + else: + html = f"{html[:index]},{html[index+1:]}" # replace for a ',' + # index = index-1 + # html = f"{html[:index]}).html({html[index+1:]}" # replace for a ',' + # increase_index +=6 + # strip any comments cleaned=[] for line in html.splitlines(): - print('smelly fanny!') if "" + pattern = re.compile(reg) + html = re.sub( pattern, f'{tag}("""', html )#, flags=re.IGNORECASE ) + + # second pass. atrributed + reg = f"<{tag}" + pattern = re.compile(reg) + html = re.sub( pattern, f'{tag}("""', html )#, flags=re.IGNORECASE ) + + reg = f"" + pattern = re.compile(reg) + html = re.sub( pattern, '""")', html)#, flags=re.IGNORECASE ) + + reg = f"/>" + pattern = re.compile(reg) + html = re.sub( pattern, '""")', html)#, flags=re.IGNORECASE ) + + + html = ')'.join(html.split(',)')) + + print(html) + # return eval('print("test")') # return eval('Location()') # return eval('html()') diff --git a/domonic/dom.py b/domonic/dom.py index f7afebf0..6cbdbc9a 100644 --- a/domonic/dom.py +++ b/domonic/dom.py @@ -39,16 +39,16 @@ def __init__(self): class EventTarget: - def __init__(): + def __init__(self): self.listeners = {} # TODO - event: str, function, useCapture: bool - def addEventListener(_type, callback): + def addEventListener(self, _type, callback): if _type not in self.listeners: self.listeners[_type] = [] self.listeners[_type].append(callback) - def removeEventListener(_type, callback): + def removeEventListener(self, _type, callback): if _type not in self.listeners: return @@ -60,7 +60,7 @@ def removeEventListener(_type, callback): stack.remove(thing) return - def dispatchEvent(event): + def dispatchEvent(self, event): if event._type not in self.listeners: return True @@ -161,13 +161,12 @@ def __init__(self, *args, **kwargs): pass # def accessKey( key: str ): -> None - ''' Sets or returns the accesskey attribute of an element''' - + # ''' Sets or returns the accesskey attribute of an element''' # return # example # dom.getElementById("myAnchor").accessKey = "w"; - def addEventListener(event: str, function, useCapture: bool) -> None: + def addEventListener(self, event: str, function, useCapture: bool) -> None: '''Attaches an event handler to the specified element''' # return # example @@ -176,17 +175,16 @@ def addEventListener(event: str, function, useCapture: bool) -> None: # }); pass - - # def appendChild(): + def appendChild(self, item): '''Adds a new child node, to an element, as the last child node''' + # self.content = self.content + item.__str__() # return + pass def attributes(self) -> List : ''' Returns a List of an element's attributes''' return self.attributes - - def innerHTML(self, *args) -> str : ''' Sets or returns the content of an element''' self.content = ''.join([each.__str__() for each in args]) @@ -194,181 +192,347 @@ def innerHTML(self, *args) -> str : def html(self, *args) -> str : return self.innerHTML(*args) # jquery - - """ - def blur(): + def blur(self): '''Removes focus from an element''' - def childElementCount(): + pass + def childElementCount(self): ''' Returns the number of child elements an element has''' - def childNodes(): + pass + def childNodes(self): ''' Returns a collection of an element's child nodes (including text and comment nodes)''' - def children(): + pass + def children(self): ''' Returns a collection of an element's child element (excluding text and comment nodes)''' - def classList(): + pass + def classList(self): ''' Returns the class name(s) of an element''' - def className(): + pass + def className(self): ''' Sets or returns the value of the class attribute of an element''' - def click(): - '''Simulates a mouse-click on an element''' - def clientHeight(): - ''' Returns the height of an element, including padding''' - def clientLeft(): - ''' Returns the width of the left border of an element''' - def clientTop(): - ''' Returns the width of the top border of an element''' - def clientWidth(): - ''' Returns the width of an element, including padding''' - def cloneNode(): - '''Clones an element''' - def compareDocumentPosition(): - '''Compares the document position of two elements''' - def contains(): - '''Returns true if a node is a descendant of a node, otherwise false''' - def contentEditable(): - ''' Sets or returns whether the content of an element is editable or not''' - def dir(): - ''' Sets or returns the value of the dir attribute of an element''' - def exitFullscreen(): - '''Cancels an element in fullscreen mode''' - def firstChild(): - ''' Returns the first child node of an element''' - def firstElementChild(): - ''' Returns the first child element of an element''' - def focus(): - '''Gives focus to an element''' - def getAttribute(): - '''Returns the specified attribute value of an element node''' - def getAttributeNode(): - '''Returns the specified attribute node''' - def getBoundingClientRect(): - '''Returns the size of an element and its position relative to the viewport''' - def getElementsByClassName(): - '''Returns a collection of all child elements with the specified class name''' - def getElementsByTagName(): - '''Returns a collection of all child elements with the specified tag name''' - def hasAttribute(): - '''Returns true if an element has the specified attribute, otherwise false''' - def hasAttributes(): - '''Returns true if an element has any attributes, otherwise false''' - def hasChildNodes(): - '''Returns true if an element has any child nodes, otherwise false''' - def id(): - ''' Sets or returns the value of the id attribute of an element''' - def innerText(): - ''' Sets or returns the text content of a node and its descendants''' - def insertAdjacentElement(): - '''Inserts a HTML element at the specified position relative to the current element''' - def insertAdjacentHTML(): - '''Inserts a HTML formatted text at the specified position relative to the current element''' - def insertAdjacentText(): - '''Inserts text into the specified position relative to the current element''' - def insertBefore(): - '''Inserts a new child node before a specified, existing, child node''' - def isContentEditable(): - ''' Returns true if the content of an element is editable, otherwise false''' - def isDefaultNamespace(): - '''Returns true if a specified namespaceURI is the default, otherwise false'''(): - def isEqualNode(): - '''Checks if two elements are equal''' - def isSameNode(): - '''Checks if two elements are the same node''' - def isSupported(): - '''Returns true if a specified feature is supported on the element''' - def lang(): - ''' Sets or returns the value of the lang attribute of an element''' - def lastChild(): - ''' Returns the last child node of an element''' - def lastElementChild(): - ''' Returns the last child element of an element''' - def namespaceURI(): - ''' Returns the namespace URI of an element''' - def nextSibling(): - ''' Returns the next node at the same node tree level''' - def nextElementSibling(): - ''' Returns the next element at the same node tree level''' - def nodeName(): - ''' Returns the name of a node''' - def nodeType(): - ''' Returns the node type of a node''' - def nodeValue(): - ''' Sets or returns the value of a node''' - def normalize(): - '''Joins adjacent text nodes and removes empty text nodes in an element''' - def offsetHeight(): - ''' Returns the height of an element, including padding, border and scrollbar''' - def offsetWidth(): - ''' Returns the width of an element, including padding, border and scrollbar''' - def offsetLeft(): - ''' Returns the horizontal offset position of an element''' - def offsetParent(): - ''' Returns the offset container of an element''' - def offsetTop(): - ''' Returns the vertical offset position of an element''' - def ownerDocument(): - ''' Returns the root element (document object) for an element''' - def parentNode(): - ''' Returns the parent node of an element''' - def parentElement(): - ''' Returns the parent element node of an element''' - def previousSibling(): - ''' Returns the previous node at the same node tree level''' - def previousElementSibling(): - ''' Returns the previous element at the same node tree level''' - def querySelector(): - '''Returns the first child element that matches a specified CSS selector(s) of an element''' - def querySelectorAll(): - '''Returns all child elements that matches a specified CSS selector(s) of an element''' - def remove(): - '''Removes the element from the DOM''' - def removeAttribute(): - '''Removes a specified attribute from an element''' - def removeAttributeNode(): - '''Removes a specified attribute node, and returns the removed node''' - def removeChild(): - '''Removes a child node from an element''' - def removeEventListener(): - '''Removes an event handler that has been attached with the addEventListener() method''' - def replaceChild(): - '''Replaces a child node in an element''' - def requestFullscreen(): - '''Shows an element in fullscreen mode''' - def scrollHeight(): - ''' Returns the entire height of an element, including padding''' - def scrollIntoView(): - '''Scrolls the specified element into the visible area of the browser window''' - def scrollLeft(): - ''' Sets or returns the number of pixels an element's content is scrolled horizontally''' - def scrollTop(): - ''' Sets or returns the number of pixels an element's content is scrolled vertically''' - def scrollWidth(): - ''' Returns the entire width of an element, including padding''' - def setAttribute(): - '''Sets or changes the specified attribute, to the specified value''' - def setAttributeNode(): - '''Sets or changes the specified attribute node''' - def style(): - ''' Sets or returns the value of the style attribute of an element''' - def tabIndex(): - ''' Sets or returns the value of the tabindex attribute of an element''' - def tagName(): - ''' Returns the tag name of an element''' - def textContent(): - ''' Sets or returns the textual content of a node and its descendants''' - def title(): - ''' Sets or returns the value of the title attribute of an element''' - def toString(): - '''Converts an element to a string''' - """ + pass + def click(self): + '''Simulates a mouse-click on an element''' + pass + + def clientHeight(self): + ''' Returns the height of an element, including padding''' + pass + def clientLeft(self): + ''' Returns the width of the left border of an element''' + pass + def clientTop(self): + ''' Returns the width of the top border of an element''' + pass + def clientWidth(self): + ''' Returns the width of an element, including padding''' + pass + def cloneNode(self): + '''Clones an element''' + pass + def compareDocumentPosition(self): + '''Compares the document position of two elements''' + pass + def contains(self): + '''Returns true if a node is a descendant of a node, otherwise false''' + pass + def contentEditable(self): + ''' Sets or returns whether the content of an element is editable or not''' + pass -class Document(Element): + def dir(self): + ''' Sets or returns the value of the dir attribute of an element''' + pass - # @staticmethod - # baseURI = type('baseURI', (static_function,), {'baseURI':'eventual.technology'}) - # baseURI = static_function("eventual.technology", lambda:True, lambda:False) + def exitFullscreen(self): + '''Cancels an element in fullscreen mode''' + pass + + def firstChild(self): + ''' Returns the first child node of an element''' + pass + + def firstElementChild(self): + ''' Returns the first child element of an element''' + pass + + def focus(self): + '''Gives focus to an element''' + pass + + def getAttribute(self, attribute: str) -> str: + '''Returns the specified attribute value of an element node''' + try: + return self.kwargs[attribute] + except Exception as e: + print('failed to get attribute') + return '' + + def getAttributeNode(self, attribute: str) -> str: + '''Returns the specified attribute node''' + try: + return f"{attribute}={self.kwargs[attribute]}" + except Exception as e: + print('failed to get attribute') + return '' + + def getBoundingClientRect(self): + '''Returns the size of an element and its position relative to the viewport''' + pass + + def getElementsByClassName(self): + '''Returns a collection of all child elements with the specified class name''' + pass + + def getElementsByTagName(self, tag : str) -> List: + '''Returns a collection of all child elements with the specified tag name''' + reg = f"(<{tag}.*?>.+?)" + + closed_tags = ["base","link","meta","hr","br","wbr","img","embed","param","source","track","area","col","input","keygen","command"] + if tag in closed_tags: + reg = f"(<{tag}.*?/>)" + + pattern = re.compile(reg) + tags = re.findall(pattern,str(self)) + return tags + + def hasAttribute(self, attribute: str) -> str: + '''Returns true if an element has the specified attribute, otherwise false''' + try: + return f"{attribute}={self.kwargs[attribute]}" + except Exception as e: + print('failed to get attribute') + return '' + + def hasAttributes(self) -> bool: + '''Returns true if an element has any attributes, otherwise false''' + if len(self.kwargs)>0: + return True + else: + return False + + def hasChildNodes(self): + '''Returns true if an element has any child nodes, otherwise false''' + pass + + def id(self): + ''' Sets or returns the value of the id attribute of an element''' + pass + + def innerText(self): + ''' Sets or returns the text content of a node and its descendants''' + pass + + def insertAdjacentElement(self): + '''Inserts a HTML element at the specified position relative to the current element''' + pass + + def insertAdjacentHTML(self): + '''Inserts a HTML formatted text at the specified position relative to the current element''' + pass + + def insertAdjacentText(self): + '''Inserts text into the specified position relative to the current element''' + pass + + def insertBefore(self): + '''Inserts a new child node before a specified, existing, child node''' + pass + + def isContentEditable(self): + ''' Returns true if the content of an element is editable, otherwise false''' + pass + + def isDefaultNamespace(self): + '''Returns true if a specified namespaceURI is the default, otherwise false''' + pass + + def isEqualNode(self): + '''Checks if two elements are equal''' + pass + + def isSameNode(self): + '''Checks if two elements are the same node''' + pass + + def isSupported(self): + '''Returns true if a specified feature is supported on the element''' + pass + + def lang(self): + ''' Sets or returns the value of the lang attribute of an element''' + pass + + def lastChild(self): + ''' Returns the last child node of an element''' + pass + + def lastElementChild(self): + ''' Returns the last child element of an element''' + pass + + def namespaceURI(self): + ''' Returns the namespace URI of an element''' + pass + + def nextSibling(self): + ''' Returns the next node at the same node tree level''' + pass + + def nextElementSibling(self): + ''' Returns the next element at the same node tree level''' + pass + + def nodeName(self): + ''' Returns the name of a node''' + pass + + def nodeType(self): + ''' Returns the node type of a node''' + pass + + def nodeValue(self): + ''' Sets or returns the value of a node''' + pass + + def normalize(self): + '''Joins adjacent text nodes and removes empty text nodes in an element''' + pass + + def offsetHeight(self): + ''' Returns the height of an element, including padding, border and scrollbar''' + pass + + def offsetWidth(self): + ''' Returns the width of an element, including padding, border and scrollbar''' + pass + + def offsetLeft(self): + ''' Returns the horizontal offset position of an element''' + pass + + def offsetParent(self): + ''' Returns the offset container of an element''' + pass + + def offsetTop(self): + ''' Returns the vertical offset position of an element''' + pass + + def ownerDocument(self): + ''' Returns the root element (document object) for an element''' + pass + + def parentNode(self): + ''' Returns the parent node of an element''' + pass + + def parentElement(self): + ''' Returns the parent element node of an element''' + pass + + def previousSibling(self): + ''' Returns the previous node at the same node tree level''' + pass + + def previousElementSibling(self): + ''' Returns the previous element at the same node tree level''' + pass + + def querySelector(self): + '''Returns the first child element that matches a specified CSS selector(s) of an element''' + pass + + def querySelectorAll(self): + '''Returns all child elements that matches a specified CSS selector(s) of an element''' + pass + + def remove(self): + '''Removes the element from the DOM''' + pass + + def removeAttribute(self): + '''Removes a specified attribute from an element''' + pass + + def removeAttributeNode(self): + '''Removes a specified attribute node, and returns the removed node''' + pass + + def removeChild(self): + '''Removes a child node from an element''' + pass + + def removeEventListener(self): + '''Removes an event handler that has been attached with the addEventListener() method''' + pass + + def replaceChild(self): + '''Replaces a child node in an element''' + pass + + def requestFullscreen(self): + '''Shows an element in fullscreen mode''' + pass + + def scrollHeight(self): + ''' Returns the entire height of an element, including padding''' + pass + + def scrollIntoView(self): + '''Scrolls the specified element into the visible area of the browser window''' + pass + + def scrollLeft(self): + ''' Sets or returns the number of pixels an element's content is scrolled horizontally''' + pass + + def scrollTop(self): + ''' Sets or returns the number of pixels an element's content is scrolled vertically''' + pass + + def scrollWidth(self): + ''' Returns the entire width of an element, including padding''' + pass + + def setAttribute(self): + '''Sets or changes the specified attribute, to the specified value''' + pass + + def setAttributeNode(self): + '''Sets or changes the specified attribute node''' + pass + + def style(self): + ''' Sets or returns the value of the style attribute of an element''' + pass + + def tabIndex(self): + ''' Sets or returns the value of the tabindex attribute of an element''' + pass + + def tagName(self): + ''' Returns the tag name of an element''' + pass + + def textContent(self): + ''' Sets or returns the textual content of a node and its descendants''' + pass + + def title(self): + ''' Sets or returns the value of the title attribute of an element''' + pass + + def toString(self): + '''Converts an element to a string''' + pass + + + +class Document(Element): # baseURI = "eventual.technology" @@ -412,15 +576,15 @@ def _get_tags(self, tag): '''Adopts a node from another document''' # return - def anchors(): + def anchors(self): ''' Returns a collection of all elements in the document that have a name attribute''' return - def applets(): + def applets(self): ''' Returns a collection of all elements in the document''' return - # def baseURI(): + # def baseURI(self): ''' Returns the absolute base URI of a document''' # return self.uri @@ -486,39 +650,39 @@ def body(self, content): '''Creates a Text node''' # return - # def defaultView(): + # def defaultView(self): ''' Returns the window object associated with a document, or null if none is available.''' # return - # def designMode(): + # def designMode(self): ''' Controls whether the entire document should be editable or not.''' # return - def doctype(): + def doctype(self): ''' Returns the Document Type Declaration associated with the document''' return - def documentElement(): + def documentElement(self): ''' Returns the Document Element of the document (the element)''' return - # def documentMode(): + # def documentMode(self): ''' Returns the mode used by the browser to render the document''' # return - def domain(): + def domain(self): ''' Returns the domain name of the server that loaded the document''' return - # def domConfig(): + # def domConfig(self): '''Obsolete. Returns the DOM configuration of the document''' # return - def embeds(): + def embeds(self): ''' Returns a collection of all elements the document''' return - # def execCommand(): + # def execCommand(self): '''Invokes the specified clipboard operation on the element currently having focus.''' # return @@ -540,27 +704,23 @@ def forms(self): '''Returns a Boolean value indicating whether the document can be viewed in fullscreen mode''' # return - def getElementById(): + def getElementById(self): '''Returns the element that has the ID attribute with the specified value''' return - def getElementsByClassName(): + def getElementsByClassName(self): '''Returns a NodeList containing all elements with the specified class name''' return - def getElementsByName(): + def getElementsByName(self): '''Returns a NodeList containing all elements with a specified name''' return - def getElementsByTagName(): - '''Returns a NodeList containing all elements with the specified tag name''' - return - # def hasFocus(): '''Returns a Boolean value indicating whether the document has focus''' # return - def head(): + def head(self): ''' Returns the element of the document''' return @@ -589,31 +749,36 @@ def images(self): ''' Returns the date and time the document was last modified''' # return - def links(): + def links(self): ''' Returns a collection of all and elements in the document that have a href attribute''' - return + tag = "a" + reg = f"(<{tag}.*?/>)" + pattern = re.compile(reg) + tags = re.findall(pattern,str(self)) + return tags + - def normalize(): + def normalize(self): '''Removes empty Text nodes, and joins adjacent nodes''' return - def normalizeDocument(): + def normalizeDocument(self): '''Removes empty Text nodes, and joins adjacent nodes''' return - # def open(): + # def open(self): '''Opens an HTML output stream to collect output from document.write()''' # return - def querySelector(): + def querySelector(self): '''Returns the first element that matches a specified CSS selector(s) in the document''' return - def querySelectorAll(): + def querySelectorAll(self): '''Returns a static NodeList containing all elements that matches a specified CSS selector(s) in the document''' return - # def readyState(): + # def readyState(self): ''' Returns the (loading) status of the document''' # return @@ -625,7 +790,7 @@ def querySelectorAll(): '''Removes an event handler from the document (that has been attached with the addEventListener() method)''' # return - def renameNode(node, namespaceURI, nodename): + def renameNode(self, node, namespaceURI, nodename): '''Renames the specified node''' return @@ -655,16 +820,16 @@ def title(self) -> str: print('document has no title') return '' - def URL(): + def URL(self): ''' Returns the full URL of the HTML document''' pass - def write( html: str = "" ) -> None: + def write(self, html: str = "" ) -> None: '''Writes HTML expressions or JavaScript code to a document''' # doc = html pass - def writeln( html: str = "" ) -> None: + def writeln( self, html: str = "" ) -> None: '''Same as write(), but adds a newline character after each statement''' # doc = html pass diff --git a/domonic/html.py b/domonic/html.py index 5ccfbbcc..bdb0f161 100644 --- a/domonic/html.py +++ b/domonic/html.py @@ -175,6 +175,7 @@ def __str__(self): keygen = type('keygen', (closed_tag, Element), {'name':'keygen'}) command = type('command', (closed_tag, Element), {'name':'command'}) +main = type('command', (tag, Element), {'name':'main'}) # TODO - y was this missing? # TODO - this can't be added at the mo. need to push it class doctype(): diff --git a/domonic/javascript.py b/domonic/javascript.py index 7cc0ae14..179a1bd3 100644 --- a/domonic/javascript.py +++ b/domonic/javascript.py @@ -13,7 +13,7 @@ # class js_object(object): - def valueOf(): + def valueOf(self): """ Returns the primitive value of an array Array, Boolean, Date, Number, String""" pass @@ -34,7 +34,7 @@ class Math(js_object): SQRT1_2 = 0.7071067811865476 SQRT2 = 1.4142135623730951 - # TODO - pass what types of validation + # TODO - pass what types of validation? # i.e force numbers # i.e positive/negative numbers allowed # convert bool/string to number? @@ -42,7 +42,7 @@ def validate(func): def validation_decorator(*args, **kwargs): for n in args: if type(n) != float and type(n) != int: - raise ValueError("Value passed NaN") + raise ValueError("Value passed was NaN") return func(*args) return validation_decorator @@ -266,7 +266,7 @@ def isNaN(x): return False - def NaN(): + def NaN(self): """ "Not-a-Number" value """ return "NaN" @@ -301,7 +301,7 @@ def String(x): """ Converts an object's value to a string """ return str(x) - def undefined(): + def undefined(self): """ Indicates that a variable has not been assigned a value """ return None diff --git a/setup.py b/setup.py index 3579fd57..365f4dba 100644 --- a/setup.py +++ b/setup.py @@ -5,12 +5,12 @@ setup( name = 'domonic', - version = '0.0.3', + version = '0.0.4', author="@byteface", author_email="byteface@gmail.com", license="MIT", url = 'https://github.com/byteface/domonic', - download_url = 'https://github.com/byteface/pypals/archive/0.0.3.tar.gz', + download_url = 'https://github.com/byteface/pypals/archive/0.0.4.tar.gz', description = 'generate html with python 3', long_description=long_description, long_description_content_type="text/markdown", diff --git a/test_domonic.py b/test_domonic.py index 7659cebe..99d52c1b 100644 --- a/test_domonic.py +++ b/test_domonic.py @@ -32,17 +32,18 @@ def test_domonic_get(self): # page = domonic.get("https://v5.getbootstrap.com/docs/5.0/examples/checkout/") # page = domonic.get("https://v5.getbootstrap.com/docs/5.0/examples/carousel/?#") # page = domonic.get("https://v5.getbootstrap.com/docs/5.0/examples/dashboard/#") - + # page = domonic.get("https://www.google.com") + # page = domonic.get("https://www.facebook.com") # print("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<") # print(render(page)) - # dir(page) + pass def test_domonic_render(self): test = html( head( meta( _charset="utf-8"), - # meta( **{"http-equiv":"X-UA-Compatible"}, content="IE=edge"), + # meta( **{"http-equiv":"X-UA-Compatible"},, _content="IE=edge"), title("eventual.technology"), meta( _name="viewport", _content="width=device-width, initial-scale=1"), meta( _name="description", _content="eventual technology" ), @@ -77,7 +78,7 @@ def test_domonic_render_head(self): ''' test = head( meta( _charset="utf-8"), - # meta( **{"http-equiv":"X-UA-Compatible"}, content="IE=edge"), + # meta( **{"http-equiv":"X-UA-Compatible"},, _content="IE=edge"), title("byteface"), meta( _name="viewport", _content="width=device-width, initial-scale=1"), meta( _name="description", _content="eventual technology" ), @@ -101,7 +102,7 @@ def test_domonic_render_head(self): # link( _rel="dns-prefetch", _href="https://github.githubassets.com" ) # TOOD - list of 'classless' # link( _crossorigin="anonymous", _media="all", _integrity="sha512-1234", _rel="stylesheet", _href="styles.css" ) - # link( rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="GitHub") + # link( _rel="search", _type="application/opensearchdescription+xml" href="/opensearch.xml" title="GitHub") meta( _property="fb:app_id", _content=""), meta( _name="google-site-verification", _content="" ), @@ -118,6 +119,7 @@ def test_domonic_render_head(self): def test_domonic_render_bs5_checkout(self): + ''' test = html( head().html( meta(_charset="utf-8"), @@ -127,7 +129,7 @@ def test_domonic_render_bs5_checkout(self): meta(_name="generator", _content="Hugo 0.72.0"), title("Checkout example · Bootstrap"), link(_rel="canonical", _href="https://v5.getbootstrap.com/docs/5.0/examples/checkout/"), - link(_href="/docs/5.0/dist/css/bootstrap.min.css", _rel="stylesheet", _integrity="sha384-12345", _crossorigin="anonymous"), + link(_href="/docs/5.0/dist/css/bootstrap.min.css", _rel="stylesheet", __integrity="sha384-12345", __crossorigin="anonymous"), link(_rel="apple-touch-icon", _href="/docs/5.0/assets/img/favicons/apple-touch-icon.png", _sizes="180x180"), link(_rel="icon", _href="/docs/5.0/assets/img/favicons/favicon-32x32.png", _sizes="32x32", _type="image/png"), link(_rel="icon", _href="/docs/5.0/assets/img/favicons/favicon-16x16.png", _sizes="16x16", _type="image/png"), @@ -341,6 +343,460 @@ def test_domonic_render_bs5_checkout(self): # print(render(test,'bs5_test_checkout.html')) print(render(test)) + ''' + pass + + + + def test_domonic_render_bs5_carousel(self): + ''' + test = html(_lang="en").html( + head( + meta( _charset="utf-8"), + meta( _name="viewport", _content="_width=device-width, initial-scale=1"), + meta( _name="description", _content=""), + meta( _name="author", _content="Mark Otto, Jacob Thornton, and Bootstrap contributors"), + meta( _name="generator", _content="Hugo 0.72.0"), + title("Carousel Template · Bootstrap"), + link( _rel="canonical", _href="https://v5.getbootstrap.com/docs/5.0/examples/carousel/"), + link( _href="/docs/5.0/dist/css/bootstrap.min.css", _rel="stylesheet", _integrity="sha384-1234", _crossorigin="anonymous"), + link( _rel="apple-touch-icon", _href="/docs/5.0/assets/img/favicons/apple-touch-icon.png", _sizes="180x180"), + link( _rel="icon", _href="/docs/5.0/assets/img/favicons/favicon-32x32.png", _sizes="32x32", _type="image/png"), + link( _rel="icon", _href="/docs/5.0/assets/img/favicons/favicon-16x16.png", _sizes="16x16", _type="image/png"), + link( _rel="manifest", _href="/docs/5.0/assets/img/favicons/manifest.json"), + link( _rel="mask-icon", _href="/docs/5.0/assets/img/favicons/safari-pinned-tab.svg", _color="#7952b3"), + link( _rel="icon", _href="/docs/5.0/assets/img/favicons/favicon.ico"), + meta( _name="theme-color", _content="#7952b3"), + style(""" + .bd-placeholder-img { + font-size: 1.125rem; + text-anchor: middle; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + } + @media (min-width: 768px) { + .bd-placeholder-img-lg { + font-size: 3.5rem; + } + } + """), + link( _href="carousel.css", _rel="stylesheet"), + ), + body( + header( + nav( _class="navbar navbar-expand-md navbar-dark fixed-top bg-dark").html( + div( _class="container-fluid").html( + a("Carousel", _class="navbar-brand", _href="#"), + button(span( _class="navbar-toggler-icon"), _class="navbar-toggler", _type="button", **{"_data-toggle":"collapse"}, **{"_data-target":"#navbarCollapse"}, **{"_aria-controls":"navbarCollapse"}, **{"_aria-expanded":"false"}, **{"_aria-label":"Toggle navigation"}) + ), + div( _class="collapse navbar-collapse", _id="navbarCollapse").html( + ul( _class="navbar-nav mr-auto mb-2 mb-md-0").html( + li(a("Home", _class="nav-link", **{"_aria-current":"page"}, _href="#"), _class="nav-item active"), + li(a("Link", _class="nav-link", _href="#"), _class="nav-item"), + li(a("Disabled", _class="nav-link disabled", _href="#", _tabindex="-1", **{"_aria-disabled":"true"}), + _class="nav-item" + ) + ), + form( _class="d-flex").html( + input(button("Search", _class="btn btn-outline-success", _type="submit"), + _class="form-control mr-2", _type="search", _placeholder="Search", **{"_aria-label":"Search"}, + ) + ) + ) + ) + ), + main( + div( _id="myCarousel", _class="carousel slide", **{"_data-ride":"carousel"}).html( + ol( _class="carousel-indicators").html( + li( **{"_data-target":"#myCarousel"}, **{"_data-slide-to":"0"}, _class="active"), + li( **{"_data-target":"#myCarousel"}, **{"_data-slide-to":"1"}), + li( **{"_data-target":"#myCarousel"}, **{"_data-slide-to":"2"}) + ), + div( _class="carousel-inner").html( + div( _class="carousel-item active").html( + """""", + div( _class="container").html( + div( _class="carousel-caption text-left").html( + h1("Example headline."), + p("Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit."), + p(a("Sign up today", _class="btn btn-lg btn-primary", _href="#", _role="button")) + ) + ) + ), + div( _class="carousel-item").html( + """""", + div( _class="container").html( + div( _class="carousel-caption").html( + h1("Another example headline."), + p("Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit."), + p(a("Learn more", _class="btn btn-lg btn-primary", _href="#", _role="button")) + ) + ) + ), + div( _class="carousel-item").html( + """""", + div( _class="container").html( + div( _class="carousel-caption text-right").html( + h1("One more for good measure."), + p("Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit."), + p(a("Browse gallery", _class="btn btn-lg btn-primary", _href="#", _role="button")) + ) + ) + ) + ), + a( _class="carousel-control-prev", _href="#myCarousel", _role="button", **{"_data-slide":"prev"}).html( + span(**{"_aria-hidden":"true"}, _class="carousel-control-prev-icon"), + span("Previous", _class="sr-only") + ), + a( _class="carousel-control-next", _href="#myCarousel", _role="button", **{"_data-slide":"next"}).html( + span( _class="carousel-control-next-icon", **{"_aria-hidden":"true"}), + span("Next", _class="sr-only") + ) + ), + div( _class="container marketing").html( + div( _class="row").html( + div( _class="col-lg-4").html( + """140x140""", + h2("Heading"), + p("Donec sed odio dui. Etiam porta sem malesuada magna mollis euismod. Nullam id dolor id nibh ultricies vehicula ut id elit. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Praesent commodo cursus magna."), + p(a("View details »", _class="btn btn-secondary", _href="#", _role="button")) + ), + div( _class="col-lg-4").html( + """140x140""", + h2("Heading"), + p("Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Cras mattis consectetur purus sit amet fermentum. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh."), + p(a("View details »", _class="btn btn-secondary", _href="#", _role="button")) + ), + div( _class="col-lg-4").html( + """140x140""", + h2("Heading"), + p("Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus."), + p(a("View details »", _class="btn btn-secondary", _href="#", _role="button") + ), + hr( _class="featurette-divider"), + div( _class="row featurette").html( + div( _class="col-md-7").html( + h2("First featurette heading.", span( _class="text-muted"), "It’ll blow your mind.", _class="featurette-heading"), + p("Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis euismod semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus commodo.", + _class="lead") + ), + div("""500x500""", + _class="col-md-5" + ) + ), + hr( _class="featurette-divider"), + div( _class="row featurette").html( + div( _class="col-md-7 order-md-2").html( + h2( "Oh yeah, it’s that good.", span( _class="text-muted"), "See for yourself.", _class="featurette-heading")), + p("Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis euismod semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus commodo.", _class="lead") + ), + div( _class="col-md-5 order-md-1").html( + """500x500""" + ) + ), + hr( _class="featurette-divider"), + div( _class="row featurette").html( + div( _class="col-md-7").html( + h2("Checkmate.", "And lastly, this one.", span( _class="text-muted"), _class="featurette-heading" ), + p("Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis euismod semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus commodo.", + _class="lead") + ), + div("""500x500""", + _class="col-md-5" + ) + ), + hr( _class="featurette-divider"), + footer( _class="container").html( + p("Back to top", a(_href="#"), _class="float-right"), + p("© 2017-2020 Company, Inc. ·", a("Privacy", _href="#"), "·", a("Terms", _href="#")) + ) + ), + script( _src="/docs/5.0/dist/js/bootstrap.bundle.min.js", _integrity="sha384-12345", _crossorigin="anonymous" ) + ) + ) + ) + ) + ''' + # print(render(test,'bs5_test_carousel.html')) + # print(render(test)) + pass + + + + def test_domonic_render_bs5_dashboard(self): + ''' + root = html(_lang="en") + test = root.html( + head( + meta(_charset="utf-8"), + meta(_name="viewport", _content="width=device-width, initial-scale=1"), + meta(_name="description", _content=""), + meta(_name="author", _content="Mark Otto, Jacob Thornton, and Bootstrap contributors"), + meta(_name="generator", _content="Hugo 0.72.0"), + title("Dashboard Template · Bootstrap"), + link(_rel="canonical", _href="https://v5.getbootstrap.com/docs/5.0/examples/dashboard/"), + link(_href="/docs/5.0/dist/css/bootstrap.min.css", _rel="stylesheet", _integrity="sha384-1234", _crossorigin="anonymous"), + link(_rel="apple-touch-icon", _href="/docs/5.0/assets/img/favicons/apple-touch-icon.png", _sizes="180x180"), + link(_rel="icon", _href="/docs/5.0/assets/img/favicons/favicon-32x32.png", _sizes="32x32", _type="image/png"), + link(_rel="icon", _href="/docs/5.0/assets/img/favicons/favicon-16x16.png", _sizes="16x16", _type="image/png"), + link(_rel="manifest", _href="/docs/5.0/assets/img/favicons/manifest.json"), + link(_rel="mask-icon", _href="/docs/5.0/assets/img/favicons/safari-pinned-tab.svg", _color="#7952b3"), + link(_rel="icon", _href="/docs/5.0/assets/img/favicons/favicon.ico"), + meta(_name="theme-color", _content="#7952b3"), + style(""" + .bd-placeholder-img { + font-size: 1.125rem; + text-anchor: middle; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + } + @media (min-width: 768px) { + .bd-placeholder-img-lg { + font-size: 3.5rem; + } + } + """), + link(_href="dashboard.css", _rel="stylesheet"), + ), + body( + nav(_class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow").html( + a("Company name", _class="navbar-brand col-md-3 col-lg-2 mr-0 px-3", _href="#"), + button(span(_class="navbar-toggler-icon"), + _class="navbar-toggler position-absolute d-md-none collapsed", + _type="button", + **{"_data-toggle":"collapse"}, + **{"_data-target":"#sidebarMenu"}, + **{"_aria-controls":"sidebarMenu"}, + **{"_aria-expanded":"false"}, + **{"_aria-label":"Toggle navigation"} + ), + input(_class="form-control form-control-dark w-100", _type="text", _placeholder="Search", **{"_aria-label":"Search"}).html( + ul(_class="navbar-nav px-3").html( + li(a("Sign out",_class="nav-link", _href="#"), _class="nav-item text-nowrap") + ) + ), + div(_class="container-fluid").html( + div(_class="row").html( + nav(_id="sidebarMenu", _class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse").html( + div(_class="position-sticky pt-3").html( + ul(_class="nav flex-column").html( + li( + a(span(**{"_data-feather":"home"}), "Dashboard", _class="nav-link active", **{"_aria-current":"page"}, _href="#"), + _class="nav-item" + ), + li( + a(span(**{"_data-feather":"file"}), "Orders", _class="nav-link", _href="#"), + _class="nav-item" + ), + li( + a(span(**{"_data-feather":"shopping-cart"}), "Products", _class="nav-link", _href="#"), + _class="nav-item" + ), + li( + a(span(**{"_data-feather":"users"}), "Customers", _class="nav-link", _href="#"), + _class="nav-item" + ), + li( + a(span(**{"_data-feather":"bar-chart-2"}), "Reports", _class="nav-link", _href="#"), + _class="nav-item" + ), + li( + a(span(**{"_data-feather":"layers"}),"Integrations",_class="nav-link", _href="#"), + _class="nav-item" + ) + ) + ), + h6(_class="sidebar-heading d-flex justify-content-between align-items-center px-3 mt-4 mb-1 text-muted").html( + span("Saved reports"), + a(span(**{"_data-feather":"plus-circle"}, **{"_aria-label":"Add a new report"}), + _class="link-secondary", _href="#") + ) + ), + ul(_class="nav flex-column mb-2").html( + li( + a(span(**{"_data-feather":"file-text"}), "Current month", _class="nav-link", _href="#"), + _class="nav-item" + ), + li( + a(span(**{"_data-feather":"file-text"}), "Last quarter", _class="nav-link", _href="#"), + _class="nav-item" + ), + li( + a(span(**{"_data-feather":"file-text"}), "Social engagement", _class="nav-link", _href="#"), + _class="nav-item" + ), + li( + a(span(**{"_data-feather":"file-text"}), "Year-end sale", _class="nav-link", _href="#"), + _class="nav-item" + ) + ) + ) + ), + main(_class="col-md-9 ml-sm-auto col-lg-10 px-md-4").html( + div(_class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom").html( + h1("Dashboard", _class="h2"), + div(_class="btn-toolbar mb-2 mb-md-0").html( + div(_class="btn-group mr-2").html( + button("Share", _type="button", _class="btn btn-sm btn-outline-secondary"), + button("Export", _type="button", _class="btn btn-sm btn-outline-secondary") + ), + button(span(**{"_data-feather":"calendar"}), "This week", _type="button", _class="btn btn-sm btn-outline-secondary dropdown-toggle") + ) + ), + canvas(_class="my-4 w-100", _id="myChart", _width="900", _height="380"), + h2("Section title"), + div(_class="table-responsive").html( + table(_class="table table-striped table-sm").html( + thead( + tr( + th(" #"), + th("Header"), + th("Header"), + th("Header"), + th("Header") + ) + ), + tbody( + tr( + td("1, 001"), + td("Lorem"), + td("ipsum"), + td("dolor"), + td("sit") + ), + tr( + td("1, 002"), + td("amet"), + td("consectetur"), + td("adipiscing"), + td("elit") + ), + tr( + td("1, 003"), + td("Integer"), + td("nec"), + td("odio"), + td("Praesent") + ), + tr( + td("1, 003"), + td("libero"), + td("Sed"), + td("cursus"), + td("ante") + ), + tr( + td("1, 004"), + td("dapibus"), + td("diam"), + td("Sed"), + td("nisi") + ), + tr( + td("1, 005"), + td("Nulla"), + td("quis"), + td("sem"), + td("at") + ), + tr( + td("1, 006"), + td("nibh"), + td("elementum"), + td("imperdiet"), + td("Duis") + ), + tr( + td("1, 007"), + td("sagittis"), + td("ipsum"), + td("Praesent"), + td("mauris") + ), + tr( + td("1, 008"), + td("Fusce"), + td("nec"), + td("tellus"), + td("sed") + ), + tr( + td("1, 009"), + td("augue"), + td("semper"), + td("porta"), + td("Mauris") + ), + tr( + td("1, 010"), + td("massa"), + td("Vestibulum"), + td("lacinia"), + td("arcu") + ), + tr( + td("1, 011"), + td("eget"), + td("nulla"), + td("Class"), + td("aptent") + ), + tr( + td("1, 012"), + td("taciti"), + td("sociosqu"), + td("ad"), + td("litora") + ), + tr( + td("1, 013"), + td("torquent"), + td("per"), + td("conubia"), + td("nostra") + ), + tr( + td("1, 014"), + td("per"), + td("inceptos"), + td("himenaeos"), + td("Curabitur") + ), + tr( + td("1, 015"), + td("sodales"), + td("ligula"), + td(" in "), + td("libero") + ) + ) + ) + ) + ) + ) + ), + script( _src="/docs/5.0/dist/js/bootstrap.bundle.min.js", _integrity="sha384-1234", _crossorigin="anonymous"), + script( _src="https://cdnjs.cloudflare.com/ajax/libs/feather-icons/4.24.1/feather.min.js", _integrity="sha384-1234", _crossorigin="anonymous"), + script( _src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js", _integrity="sha384-1234", _crossorigin="anonymous" ), + script( _src="dashboard.js" ) + ) + + # print(render(test,'bs5_test_dashboard.html')) + # print(render(test)) + + # document.getElementsByTagName("div")[0].getAttributeNode("class"); + # print(test.getElementsByTagName("div") ) + + # test = html().html(head(),body()) + # print(type(root)) + # print(root.getElementsByTagName("button")[0].getAttribute("class")) + # print(render(root)) + ''' + pass