├── .gitattributes ├── .gitignore ├── License.md ├── MANIFEST.in ├── README.md ├── htmltree ├── __init__.py ├── doc │ └── img │ │ └── quickstart.png ├── htmltree.py └── tests │ ├── client.py │ └── sanitycheck.py ├── setup.cfg └── setup.py /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto 3 | 4 | # Explicitly declare text files you want to always be normalized and converted 5 | # to native line endings on checkout. 6 | *.c text 7 | *.css text 8 | *.example text 9 | *.h text text 10 | *.html text 11 | *.ics text 12 | *.ini text 13 | *.js text 14 | *.json text 15 | *.jsonp text 16 | *.load text 17 | *.md text 18 | *.map text 19 | *.markdown text 20 | *.py text 21 | *.local text 22 | *.sh text 23 | *.xml text 24 | rc.local text 25 | 26 | # Declare files that will always have CRLF line endings on checkout. 27 | # *.sln text eol=crlf 28 | 29 | # Denote all files that are truly binary and should not be modified. 30 | *.png binary 31 | *.jpg binary 32 | *.ico 33 | *.pdf binary 34 | *.woff binary 35 | *.woff2 binary 36 | *.svg binary 37 | *.sqlite binary 38 | *.ttf binary 39 | *.eot binary 40 | *.table binary 41 | 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## File types that should not be version controlled. 2 | 3 | # Compiled source # 4 | ################### 5 | *.com 6 | *.class 7 | *.dll 8 | *.exe 9 | *.o 10 | *.so 11 | 12 | # Packages # 13 | ############ 14 | # it's better to unpack these files and commit the raw source 15 | # git has its own built in compression methods 16 | *.7z 17 | *.dmg 18 | *.gz 19 | *.iso 20 | *.jar 21 | *.rar 22 | *.tar 23 | *.zip 24 | 25 | # Logs and databases # 26 | ###################### 27 | *.db 28 | *.log 29 | *.log.* 30 | *.sql 31 | *.sqlite 32 | *.out 33 | 34 | 35 | # OS generated files # 36 | ###################### 37 | .DS_Store 38 | .DS_Store? 39 | ._* 40 | .Spotlight-V100 41 | .Trashes 42 | ehthumbs.db 43 | Thumbs.db 44 | 45 | # Editor temporary files # 46 | ########################## 47 | *.swo 48 | *.swp 49 | *.bak 50 | 51 | 52 | # UltiSnips snippet files # 53 | ########################### 54 | *.snippets 55 | 56 | ## Python specific files 57 | 58 | # Byte-compiled / optimized / DLL files 59 | __pycache__/ 60 | *.py[cod] 61 | *$py.class 62 | 63 | # C extensions 64 | *.so 65 | 66 | # Distribution / packaging 67 | .Python 68 | env/ 69 | build/ 70 | develop-eggs/ 71 | dist/ 72 | downloads/ 73 | eggs/ 74 | .eggs/ 75 | lib/ 76 | lib64/ 77 | parts/ 78 | sdist/ 79 | var/ 80 | *.egg-info/ 81 | .installed.cfg 82 | *.egg 83 | 84 | # PyInstaller 85 | # Usually these files are written by a python script from a template 86 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 87 | *.manifest 88 | *.spec 89 | 90 | # Installer logs 91 | pip-log.txt 92 | pip-delete-this-directory.txt 93 | 94 | # Unit test / coverage reports 95 | htmlcov/ 96 | .tox/ 97 | .coverage 98 | .coverage.* 99 | .cache 100 | nosetests.xml 101 | coverage.xml 102 | *,cover 103 | .hypothesis/ 104 | 105 | # Translations 106 | *.mo 107 | *.pot 108 | 109 | # Django stuff: 110 | *.log 111 | local_settings.py 112 | 113 | # Flask stuff: 114 | instance/ 115 | .webassets-cache 116 | 117 | # Scrapy stuff: 118 | .scrapy 119 | 120 | # Sphinx documentation 121 | docs/_build/ 122 | 123 | # PyBuilder 124 | target/ 125 | 126 | # IPython Notebook 127 | .ipynb_checkpoints 128 | 129 | # pyenv 130 | .python-version 131 | 132 | # celery beat schedule file 133 | celerybeat-schedule 134 | 135 | # dotenv 136 | .env 137 | 138 | # virtualenv 139 | venv/ 140 | ENV/ 141 | 142 | # Spyder project settings 143 | .spyderproject 144 | 145 | # Rope project settings 146 | .ropeproject 147 | 148 | # directories for generated files 149 | __javascript__/ 150 | __pycache__/ 151 | __html__/ 152 | 153 | 154 | -------------------------------------------------------------------------------- /License.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.md 2 | include tests/*.py 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **Table of Contents** *generated with [DocToc](http://doctoc.herokuapp.com/)* 2 | 3 | - [Python htmltree project](#python-htmltree-project) 4 | - [Create and manipulate HTML and CSS from the comfort of Python](#create-and-manipulate-html-and-css-from-the-comfort-of-python) 5 | - [Installation](#installation) 6 | - [Quick Start](#quick-start) 7 | - [Open a Python interpreter and type or paste the following](#open-a-python-interpreter-and-type-or-paste-the-following) 8 | - [Render and print the HTML](#render-and-print-the-html) 9 | - [Now add some styling and text ...](#now-add-some-styling-and-text) 10 | - [and print the result.](#and-print-the-result) 11 | - [Reserved words and hyphenated attributes](#reserved-words-and-hyphenated-attributes) 12 | - [Viewing your work](#viewing-your-work) 13 | - [Discussion](#discussion) 14 | - [Public members](#public-members) 15 | - [Rendering](#rendering) 16 | - [Usage tips](#usage-tips) 17 | - [Rolling your own](#rolling-your-own) 18 | - [Bundling](#bundling) 19 | - [Looping](#looping) 20 | - [Using htmltree with Transcrypt™](#using-htmltree-with-transcrypt) 21 | - [Writing CSS](#writing-css) 22 | - [List of wrapper functions](#list-of-wrapper-functions) 23 | # Python htmltree project 24 | 25 | ## Create and manipulate HTML and CSS from the comfort of Python 26 | * Easy to learn. Consistent, simple syntax. 27 | * 85 predefined tag functions. 28 | * Create HTML on the fly or save as static files. 29 | * Flexible usage and easy extension. 30 | * Run locally with CPython or as Javascript in the browser using Jacques De Hooge's [*Transcrypt™*](https://transcrypt.org/) Python to JS transpiler 31 | * Dependencies: Python 3.x 32 | 33 | ### Installation 34 | `pip install htmltree` 35 | 36 | ### Quick Start 37 | 38 | #### Open a Python interpreter and type or paste the following 39 | ``` 40 | from htmltree import * 41 | head = Head() 42 | body = Body() 43 | doc = Html(head, body) 44 | ``` 45 | #### Render and print the HTML 46 | ``` 47 | >>> print(doc.render(0)) 48 | 49 | 50 | 51 | 52 | 53 | 54 | ``` 55 | #### Now add some styling and text 56 | ``` 57 | who = Meta(name="author",content="Your Name Here") 58 | head.C.append(who) 59 | body.A.update(dict(style={'background-color':'black'})) 60 | banner = H1("Hello, htmltree!", _class='banner', style={'color':'green'}) 61 | body.C.append(banner) 62 | ``` 63 | #### and print the result. 64 | ``` 65 | >>> print(doc.render(0)) 66 | 67 | 68 | 69 | 70 | 71 |

72 | Hello, htmltree! 73 |

74 | 75 | 76 | ``` 77 | In the examples above, we created elements and assigned them to variables so we could alter their content later. However, we could also have written it out all at once. 78 | 79 | ``` 80 | doc = Html( 81 | Head( 82 | Meta(name="author",content="Your Name Here")), 83 | Body( 84 | H1("Hello, htmltree!", _class='banner', style={'color':'green'}), 85 | style={'background-color':'black'})) 86 | ``` 87 | 88 | That's short and clean and renders exactly the same html. It also mimics the page structure but sacrifices ease of alteration later in the execution. Your choices should come down to whether you're creating static html or dynamic content based on information that's not available until run time. 89 | 90 | ### Reserved words and hyphenated attributes 91 | Did you notice the underscore in `H1("Hello, htmltree!", _class='banner', ...)`? It's written that way because `class` is a Python keyword. Trying to use it as an identifier will raise a syntax error. 92 | 93 | As a convenience, all the wrapper functions strip off leading and trailing underscores in attribute names, so `class_` would also work. Normal HTML doesn't use underscores in attribute names so this fix is safe to use. I think `for` as a `