Skip to content

Commit

Permalink
Merge branch 'master' of github.com:codelv/enaml-web
Browse files Browse the repository at this point in the history
  • Loading branch information
frmdstryr committed Jun 5, 2021
2 parents 676be85 + 08c4537 commit bb1d65b
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 79 deletions.
12 changes: 12 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# These are supported funding model platforms

github: frmdstryr # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
119 changes: 40 additions & 79 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ See the examples folder
- [www.codelv.com](https://www.codelv.com/) - Built entirely using enaml-web
- [SMD Component search](https://github.com/frmdstryr/smd-search) - View and search a pandas dataframe

Have a site? Feel free to share it!

### Why?

It makes it easy to build websites without a lot of javascript.

### Short intro

Expand Down Expand Up @@ -110,57 +115,55 @@ python template frameworks can do (to my knowledge).

### How it works

It generates a dom of [lxml](http://lxml.de/) elements.
It simply generates a tree of [lxml](http://lxml.de/) elements.

##### Inherently secure
#### Advantages

Since an lxml dom is generated it means that your code is inherently secure from
injection as it automatically escapes all attributes. Also a closing tag cannot
be accidentally missed.
1. Inherently secure

Since it's using lxml elements instead of text, your template code is inherently secure from
injection as lxml automatically escapes all attributes. A closing tag cannot be accidentally missed.

The atom framework provides additional security by enforcing runtime type
checking and optional validation.

2. Minified by default

##### Extendable via templates and blocks

Like other template engines, enaml-web provides a "Block" node that allows
you to define a part of a template that can be overridden or extended.
Other templates engines often render a lot of useless whitespace. This does not. The response is always minified.

Enaml also provides pattern nodes for handling conditional statements, loops,
dynamic nodes based on lists or models, and nodes generated from more complex
templates (ex automatic form generation).
3. No template tags needed


##### No template tags needed

Many template engines require the use of "template tags" wrapped in `{% %}`
Some template engines require the use of "template tags" wrapped in `{% %}`
or similar to allow the use of python code to transform variables.

Since enaml _is_ python, you can use any python code directly in
your enaml components and templates. You don't need any template tags.

4. Templates can be modified

##### Testing is easier

Since the internal representation is lxml nodes, you can use lxml's xpath
queries on the dom for e2e view testing. No need to use headless browsers and
that complicated stuff (unless you're using a lot of js).
The tree can be modified after it's rendered to react to events or data changes. These
changes can be propogated out to clients (see the data binding section).


##### Component based
5. Component based

Since enaml views are like python classes, you can "subclass" and extend any
component and extend it's functionality. This enables you to quickly build
reusable components.
reusable components. This is like "web components" but it's rendered server side
so it's not slow. See [materialize-ui](https://github.com/frmdstryr/materialize) for an example.

#### Disadvantages

1. Memory usage

I'm working on components for several common css frameworks so they can simply
be installed and used.
Even though lxml is written in c and enaml uses atom objects, the memory usage may still
be more than plain string templates.

1. [materialize-ui](https://github.com/frmdstryr/materialize)
2. semantic-ui (coming soon)
3. bootstrap (coming soon)
2. HTML only

It only works with html.


## Notes

### Data binding

Expand Down Expand Up @@ -237,28 +240,30 @@ For working with a database using atom see [atom-db](https://github.com/codelv/a
The`Raw` node parses text into dom nodes (using lxml's html parser). Similarly
`Markdown` and `Code` nodes parse markdown and highlight code respectively.

For example, you can use wagtal's richtext tag to render to a dom via:
For example, you can show content from a database like tihs:

```python

from web.components.api import *
from web.core.api import *
from wagtail.core.templatetags.wagtailcore_tags import richtext
from myapp.views.base import Page

enamldef BlogPage(Page):
attr page_model: SomeModel # Page model
body.cls = 'template-blogpage'
Block:
block = parent.content
Raw:
source << richtext(page.body)
# Render source from database
source << page_model.body

```

This let's you use web wysiwyg editors to insert content into the dom.
This let's you use web wysiwyg editors to insert content into the dom. If the content
is not valid it will not mess up the rest of the page.


#### Block node
### Block nodes

You can define a base template, then overwrite parts using the `Block` node.

Expand Down Expand Up @@ -305,52 +310,8 @@ enamldef Page(Base): page:

Blocks let you either replace, append, or prepend to the content.

#### Custom Components

With enaml you can easily create reusable components and share them through
the views as you would any python class using regular python imports.

For instance, to create a
[materalize breadcrumbs component](http://materializecss.com/breadcrumbs.html)
that automatically follows the current request path, simply include the required
css/scripts in your base template, define the component as shown below:

```python

from web.components.api import *
from web.core.api import Looper

enamldef Breadcrumbs(Nav): nav:
attr path # ex. pass in a tornado request.path
attr color = ""
attr breadcrumbs << path[1:-1].split("/")
tag = 'nav'
Div:
cls = 'nav-wrapper {}'.format(nav.color)
Div:
cls = 'container'
Div:
cls = 'col s12'
Looper:
iterable << breadcrumbs
A:
href = "/{}/".format("/".join(breadcrumbs[:loop_index+1]))
cls = "breadcrumb"
text = loop_item.title()
```

then use it it as follows

```python

# in your template add
Breadcrumbs:
path << request.path

```


### Gotachas
### Gotchas

##### Text and tail nodes

Expand Down

0 comments on commit bb1d65b

Please sign in to comment.