Git Product home page Git Product logo

byteface / domonic Goto Github PK

View Code? Open in Web Editor NEW
130.0 5.0 13.0 48.49 MB

Create HTML with python 3 using a standard DOM API. Includes a python port of JavaScript for interoperability and tons of other cool features. A fast prototyping library.

Home Page: https://domonic.readthedocs.io/

License: MIT License

Python 98.55% HTML 1.27% Makefile 0.13% Shell 0.04%
python dom html dom-api javascript terminal prototype python3 hacktoberfest hacktoberfest2021 dom-manipulation opensource

domonic's Introduction


𖀐 domonic 𖀐

PyPI version Downloads Python version Build status Python package

A DOM for making HTML with python 3! (and more)

Install

python3 -m pip install domonic
# python3 -m pip install domonic --upgrade 

Creating HTML with Python 3

from domonic.html import *
print(html(body(h1('Hello, World!'))))
# <html><body><h1>Hello, World!</h1></body></html>

or to pretty format and insert the doctype, use an f-string:

mydom = html(body(h1('Hello, World!'), a("somelink", _href="somepage.html")))
print(f"{mydom}")
<!DOCTYPE html>
<html>
	<body>
		<h1>Hello, World!</h1>
		<a href="somepage.html">somelink</a>
	</body>
</html>

parsing html

Basic useage...

from domonic import domonic
mydom = domonic.parseString('<somehtml...')

To quickly parse a webapge try the window module...

from domonic.window import window
window.location = "http://www.google.com"
print(window.document.title)

Also try the xpath or css selectors on command line...

domonic -x https://google.com '//a' | uniq | sort

More

  • html : Generate html with python 3 😎
  • dom : DOM API in python 3 😲
  • javascript : js API in python 3 😳 + (dQuery, d3)
  • JSON : utils for loading / decorating / transforming
  • SVG || mathml || aframe || x3d tags - generators for popular tags
  • terminal || cmd : call terminal commands with python3 😱

See the docs/code for more features...

or examples in the repo...

Namespace

Use the tags packaage if you want a namespace. i.e.

import domonic.tags
print(domonic.tags.h1)
# or
import domonic.tags as tags
str(tags.div)
# or 
import domonic.tags as html
print(html.span)

or just import what you need...

from domonic import div, span, input as myinput, html as root

html attributes

prepend attributes with an underscore ( avoids clashing with python keywords )

test = label(_class='classname', _for="someinput")
print(test)
<label class="classname" for="someinput"></label>

rendering DOM objects

domonic is a pure python dom whos tree is composed of objects. i.e

div()
# <domonic.html.div object at 0x106b0e6b0>

cast str() on any element to render it without formatting.

el = str(div())
print(el)
# <div></div>

There's also a render method that takes 2 parameters, some domonic and an optional output file.

page = div(span('Hello World'))
render(f"{page}", 'index.html')  # notice use of f-string to pretty print the html

There's a few new rendering options. See DOMConfig.

from domonic.dom import DOMConfig
print(DOMConfig.GLOBAL_AUTOESCAPE)  # Default False
print(DOMConfig.RENDER_OPTIONAL_CLOSING_TAGS)  # Default True
print(DOMConfig.RENDER_OPTIONAL_CLOSING_SLASH)  # Defaults True
print(DOMConfig.SPACE_BEFORE_OPTIONAL_CLOSING_SLASH)  # Default False

DOM

DOM manipulation with python.

createElement

to create your own elements use the DOM API

from domonic.dom import *

site = html()
el = document.createElement('myelement')
site.appendChild(el)
print(site)
# <html><myelement></myelement></html>

There's an evolving DOM API. To learn more about the webAPI click here.

And check the code/docs to see what's currently been implemented.

mysite.querySelectorAll('button') 
mysite.querySelectorAll("a[rel=nofollow]")
mysite.querySelectorAll("a[href='#services']")
mysite.querySelectorAll("a[href$='technology']")
mysite.querySelectorAll('.fa-twitter')

somelinks = mysite.querySelectorAll("a[href*='twitter']")
for l in somelinks:
    print(l.href)

To use the DOM either reference your root 'html' node or import the dom modules global 'document'

# access the document via the html tag
mydom = html()
# mydom.getElementbyID...

# or by importing the document global
from domonic.dom import document
# document.createElement...
print(document)

javascript

There is a javascript package that mimics the js API:

from domonic.javascript import Math
print(Math.random())

from domonic.javascript import Array
myArr=Array(1,2,3)
print(myArr.splice(1))
# [2, 3]

from domonic.javascript import URL
url = URL('https://somesite.com/blog/article-one#some-hash')
print(url.protocol)  # https
print(url.host)  # somesite.com
print(url.pathname)  # /blog/article-one
print(url.hash)  # #some-hash

# Use Global class to import all the js methods from the global namespace i.e
# from domonic.javascript import Global
# Global.decodeURIComponent(...
# Global.encodeComponent(...
# Global.setInterval(...

# from domonic.javascript import Date, String, Number
# etc..

Use setInterval and clearInterval with params

from domonic.javascript import setInterval, clearInterval

x=0

def hi(inc):
    global x
    x = x+inc
    print(x)

test = setInterval(hi, 1000, 2)
import time
time.sleep(5)
clearInterval(test)
print(f"Final value of x:{x}")

Or for a single delayed function call use setTimeout, clearTimeout

from domonic.javascript import setTimeout, clearTimeout
timeoutID = setTimeout(hi, 1000)

You can call () on a stringvar to transform it into a Node

from domonic.javascript import String

test = String("Hi there!")
test('div', _style="font-color:red;")
str(test('div', _style="font-color:red;"))
# <div style="font-color:red;">Hi there!</div>

a-tags inherit URL:

from domonic.html import *

atag = a(_href="https://somesite.com:8000/blog/article-one#some-hash")
print('href:', atag.href)
# href: https://somesite.com:8000/blog/article-one#some-hash
print('protocol:', atag.protocol)
# protocol: https:
print('port:', atag.port)
# port: 8000

atag.protocol = "http"
atag.port = 8983
print(atag)
# <a href="http://somesite.com:8983/blog/article-one#some-hash">

For writing and using regular javascript, load from a src...

script(_src="/docs/5.0/dist/js/bootstrap.bundle.min.js", _integrity="sha384-1234", _crossorigin="anonymous"),
# <script src="/docs/5.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-1234" crossorigin="anonymous"></script>

or do inline js by opening triple quotes...

script("""
let itbe = ""
"""),

Styling

Styling is supported. Styles get passed to the style tag on render...

mytag = div("hi", _id="test")
mytag.style.backgroundColor = "black"
mytag.style.fontSize = "12px"
print(mytag)
# <div id="test" style="background-color:black;font-size:12px;">hi</div>

To use css use a link tag as you usually would...

link(_href="styles.css", _rel="stylesheet"),

or use triple quotes to open style tag...

style("""
.placeholder-img {
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}
"""),

decorators

use decorators to wrap elements around function results

from domonic.decorators import el

@el(html, True)
@el(body)
@el(div)
def test():
    return 'hi!'

print(test())
# <html><body><div>hi!</div></body></html>

# returns pyml objects so call str to render
assert str(test()) == '<html><body><div>hi!</div></body></html>'

It returns the tag object by default. You can pass True as a second param to the decorator to return a rendered string instead. Also accepts strings as first param i.e. custom tags.

data-tags

python doesn't allow hyphens in parameter names. so use variable keyword argument syntax for custom data-tags

div("test", **{"_data-test":"test"} )
# <div data-test="test">test</div>

or for example a colon...

t = div( **{"_:test":"something"} )
str(t)
# <div :test="something"></div>

JSON (utils)

decorate any function that returns python objects to return json instead

from domonic.decorators import as_json
import domonic.JSON as JSON

@as_json
def somefunc():
    myObj = {"hi":[1,2,3]}
    return myObj

print( somefunc() )
# {"hi":[1,2,3]}
print( JSON.is_json(somefunc()) )
# True

convert json arrays into html tables...

import domonic.JSON as JSON

# i.e. containting flat json array of dicts... [{"id":"01","name": "some item"},{"id":"02","name": "some other item"}]

json_data = JSON.parse_file('somefile.json')
mytable = JSON.tablify(json_data)
print(mytable)

convert json arrays into csv files...

import domonic.JSON as JSON

json_data = JSON.parse_file('somefile.json')
JSON.csvify(json_data, 'data.csv')

convert csv files to json...

import domonic.JSON as JSON

json_data =JSON.csv2json("data.csv")
print(json_data)

more to come...

SVG

All tags extend 'Element'. So will have DOM and magic methods available to them. See the docs.

circ = svg(
    circle(_cx="50", _cy="50", _r="40", _stroke="green", **{"_stroke-width": "4"}, _fill="yellow"),
    _width="100", _height="100",
)
mysvg = svg()
mysvg.appendChild(circ / 10)
print(mysvg)

Tweening

Tween values with the tween library:

from domonic.lerpy.easing import *
from domonic.lerpy.tween import *

someObj = {'x':0,'y':0,'z':0}
twn = Tween( someObj, { 'x':10, 'y':5, 'z':3 }, 6, Linear.easeIn )
twn.start()

aframe / x3d

3d tags can be used if you import the js

from domonic.html import *
from domonic.xml.aframe import *
from domonic.CDN import *

_scene = scene(
      box(_position="-1 0.5 -3", _rotation="0 45 0", _color="#4CC3D9"),
      sphere(_position="0 1.25 -5", _radius="1.25", _color="#EF2D5E"),
      cylinder(_position="1 0.75 -3", _radius="0.5", _height="1.5", _color="#FFC65D"),
      plane(_position="0 0 -4", _rotation="-90 0 0", _width="4", _height="4", _color="#7BC8A4"),
      sky(_color="#ECECEC")
    )

_webpage = html(head(),body(
    script(_src=CDN_JS.AFRAME_1_2), # < NOTICE you need to import aframe to use it
    str(_scene)
    )
)

render( _webpage, 'hello.html' )

dQuery (NEW)

dQuery uses the ΒΊ symbol (alt+0).

from domonic.html import *
from domonic.dQuery import ΒΊ

d = html(head(body(li(_class='things'), div(_id="test"))))

print( ΒΊ('#test') )
# <div id="test">
print( ΒΊ('.things') )
# <li class="things">
mydiv = ΒΊ('<div class="test2"></div>')
# <domonic.dQuery.o object at 0x107d5c9a0>

b = ΒΊ('#test').append(mydiv)
print(b)
# <div id="test"><div class="test2"></div></div>

Only recently started so check to see what's implemented.

terminal

There is a command line package that can call bash/unix/posix and other apps on the command line:

This package only works on nix systems as it effectively just passes stuff off to subprocess.

from domonic.terminal import *

print(ls())
print(ls("-al"))
print(ls("../"))
print(pwd())
print(mkdir('somedir'))
print(touch('somefile'))
print(git('status'))

for file in ls( "-al" ):
    print("Line : ", file)

for f in ls():
    try:
        print(f)
        print(cat(f))
    except Exception as e:
        pass

for i, l in enumerate(cat('LICENSE.txt')):
    print(i,l)

print(man("ls"))
print(echo('test'))
print(df())
print(du())

for thing in du():
    print(thing)

print(find('.'))
# print(ping('eventual.technology'))# < TODO - need to strean output
print(cowsay('moo'))
# print(wget('eventual.technology'))
print(date())
print(cal())

or just run arbitrary commands...

from domonic.terminal import command
command.run("echo hi")

Take a look at the code in 'terminal.py' to see all the commands as there's loads. (Disclaimer: not all tested.)

Windows users can use now use cmd.

from domonic.cmd import *
print(dir())
print(dir("..\\")) 

DOCS

https://domonic.readthedocs.io/

CLI

Use the command line interface to help you out.

To view the online the docs:

domonic -h

To see the version:

domonic -v

To quickly create a domonic project for prototyping:

domonic -p myproject

To evaluate some domonic pyml:

domonic -e 'html(head(),body(div()))'

To use xpath on a website from the command line:

domonic -x https://google.com '//a'

To use css selectors on a website from the command line:

domonic -q https://google.com 'a'

EXAMPLE PROJECTS

Blueberry : A browser based file OS. Working example of how components can work.

ezcron : A cron viewer

bombdisposer : A basic game

htmlx : A low dependency lightweight (DOM only) version of domonic

Checkout the docs for more examples i.e. generating sitemaps or using domonic with server frameworks like flask, django, sanic, fastapi and others.

There's also several useage examples in the repo so pull and have a look.

Join-In

Feel free to contribute if you find it useful. (I'd be grateful for help on all fronts)

Email me, message me directly if you like or create a discussion on here. Or join the discord.

If there are any methods you want that are missing or not complete yet or you think you can help make it better just update the code and send a pull request. I'll merge and releaese asap.

In the repo there's a requirements-dev.txt which is mostly the libs used in the examples.

requirements.txt are the libs used for packaging just the lib.

See also the CONTRIBUTING.md

running examples

. venv/bin/activate
pip install -r requirements-dev.txt
cd examples
python lifecalendar.py

run tests

There are tests used during dev. They are useful as code examples and to see what still needs doing.

See Makefile to run all tests:

make test  # default tests ubuntu. so will fail on window when terminal test runs. comment out locally if that's the case

or to test a single function:

python -m unittest tests.test_javascript.TestCase.test_javascript_array
python -m unittest tests.test_dQuery.TestCase.test_addClass
python -m unittest tests.test_geom.TestCase.test_vec2
python3 -m unittest tests.test_cmd.TestCase.test_cmd_dir  # only windows

or to test a whole module

python -m unittest tests.test_html
python -m unittest tests.test_CDN

to see coverage

coverage run -m unittest discover tests/
coverage report

or...

pip install pytest
pytest tests

Disclaimer

There's several more widely supported libraries doing HTML generation, DOM reading/manipulation, terminal wrappers etc. Maybe use one of those for production due to strictness and support.

This is more of a fast prototyping library.

domonic's People

Contributors

alfasst avatar arjixwastaken avatar byteface avatar code-review-doctor avatar dependabot[bot] avatar frackoverflow avatar jordan-cottle avatar kainech avatar kthy avatar lmgarret avatar shoginn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

domonic's Issues

type hints

I've been casually adding it. So feel free to put more in if you see places it won't hurt.

Exception: unable to update parent 'Comment' object has no attribute 'args'

When instantiating a domonic.html.comment (or a dom.Comment, same same) object in a Sanic response, I'm getting the exception unable to update parent 'Comment' object has no attribute 'args' (from dom.py line 193) seven to eleven times in my log. I can't reproduce it in a REPL session. I also can't figure out why I get any particular number of exceptions, but they are the same number from page load to page load.

@app.route("/test_comment")
async def test_comment(req):
    return response.html(f"{html(head(), body(comment('foo')))}")
[2021-10-11 12:39:04 +0200] [9197] [INFO] Starting worker [9197]
unable to update parent 'Comment' object has no attribute 'args'
unable to update parent 'Comment' object has no attribute 'args'
unable to update parent 'Comment' object has no attribute 'args'
unable to update parent 'Comment' object has no attribute 'args'
unable to update parent 'Comment' object has no attribute 'args'
unable to update parent 'Comment' object has no attribute 'args'
unable to update parent 'Comment' object has no attribute 'args'
unable to update parent 'Comment' object has no attribute 'args'
unable to update parent 'Comment' object has no attribute 'args'
unable to update parent 'Comment' object has no attribute 'args'
unable to update parent 'Comment' object has no attribute 'args'
[2021-10-11 12:39:15 +0200] [9197] [DEBUG] KeepAlive Timeout. Closing connection.

dquery finish get and ajax calls

i didnt do much here. just a quick test. its very lazily done but a cute feature if finished. I may not get to it for a while so there for the taking. as are many methods in this class still.

requirements upper bounds

I've been enjoying your library, it has some of the better implementations in an easy to implement way (ex. _methods)

One thing I've noticed is that you have specified that your requirements are all static (requests/urllib for example).

Because your implementation of those requirements are not really integrated into your library, would it not make more sense to create a major version upper limit?

my rec:

requests~=2.26
urllib3~=1.26

Im of course ready to be corrected on this.

timeouts -

currently missing decent setTimout and clearTimeout methods.

I'd like these to work 2 ways. async and not. so a flag needs to be added to make async=True. currently i doubled up and 2 new ones to 'Global' so the old implementations could be left alone. (not that they worked. its just a sleep.)

ideally somehow utilise the SetInterval work that was done in the past. I had avoided ayncio due to api changes between python versions. I'd get setInterval to work in one version but it would fail in another so went to 'threads' for the Job class. howeer this is only async atm. should it block during exec?

for now I can't see me getting to this for a while. so making a ticket not to use setTimeout and clearTimeout as they aren't done. But will be once I get time and can think about how I resolve these issues.

parser

I think I'm going to need a few types of parser. a normal one, one that uses python built in one, peg ones, ones that can do xml/svg/html/... as well as my evolving one. consider importing something light if it could easily output domonic style pyml. but this could do with conversations with others that are good at that kind of thing for suggestions to improve. etc.

upgrade requests to >=2.31.0

Hi! requests 2.31.0 addresses some security issues that affect versions v2.3.0 and v2.30.0. Upgrading domonic's dependency would be nice.
For context, we use domonic as a dev dependency in our stack to locally produce some html documentation files, but cannot upgrade requests since domonic has the requirement requests~=2.28.0.

Which makes me think, would it be possible to make requests as an extra dependency for people who want to load remote html? e.g. in our case we're not interested in this feature, but I see what it could be used for and I would find it reasonable to pip install domonic[requestes] if I wanted to use this feature.

Thanks!

queryselectors need updating

we have a new replacement method that can do complex css queries but for some reason it doesn't do simple ones i.e. single tags. so they needed to be merged however an issue arose as the new one used getElementByID which was using querySelctor. fuck. So I losts a ton of fucking time and broke a branch (that had my an attempt at dict setters for attribs in it). anyways. will have another attempts at merging these together to work properly again another time. Or unless someone really really complains.

import domonic.html

Hi, I'm trying to get a handle on domonic.html module via import domonic.html or from domonic import html as opposed to from domonic.html import * (to be able to do html.span("hello") instead of span("hello")). However, domonic.html is ambiguous with the value "html" that gets imported in domonic/__init__.py . I think the star import there is responsible but I'm no expert. Given that import, all of html's exports are accessible by dom; i.e. you can write dom.span("html") which would seem to accomplish my needs but I don't think was intended in the design of these modules; that is I can confusingly write import domonic as html when I want import domonic.html.

regex class - need more work

I've realised flagging some things as help wanted works. 2 tickets closed recently by someone else.

So I will make effort to let people know what I will probably be slow getting too.

Regex is a class low down my radar and I've only done what's needed as I go. if anyone needs this or wants to take it on, then go ahead. Realistically i wont get to it otherwise for a while yet as still busy on other areas.

xpath

I haven't even started to look into this. But figured i'd see if this 'up for grabs' label is worth trying.

https://up-for-grabs.net/#/

if anyone want to try xpath integration. Is there something in standard lib?. another small lib that works already with domonic? figured i'd start a discussion.

mathml example with the shim in place

i made a ticket to remember to do this. but just to note if anyone has examples of any type feel free to put them forward. I find them useful. so as long as they small ish and show of a particular feature that's not yet been shown in another example then please do consider putting it forward. thanks.

insertAdjacent

there's a few methods with insertAdjacent etc on dom which look a bit tricky. if anyone needs them feel free to push if i dont get to them.

Some tests are skipped due to duplicate names

Test names must be unique per scope otherwise the second test overrides the first one with the same name.

For example if you had a test file that does:

def test_a():
    pass

def test_a():
    pass

Then only the second test_a will be ran. More details here.

These are the tests that are overriding previously defined tests due to this problem:

def test_body(self):

I found this issue automatically, see other issues here

d3 - Tile

Tile was unfinished but ended up in the repo.

@FrackOverflow If you enjoyed fixing my polygon d3 has a tons of fun stuff. i.e d3 - heirachy

and some real beauties if you dig around. i.e. https://github.com/d3/d3-plugins/tree/master/superformula

FYI my reason for porting d3 was to create 'real world' test cases for the use of Javascript.py class in domonic.

Just so you know it was mainly done to help me evolved the Javascript class. It makes it useful for quickly porting stuff. But ideally we'd do it all in proper python as swap out the js-like useage. Just incase you wonder why the code in the d3 section in strange.

docs

js docs are particularly weak. only really auto docs with no examples.

best examples would be the use of Casting to get the method you need.

MutationObserver

While answering a question on stackoverflow today i realised that domonics mutationobserver is still commented out as TODO but also querySelectorAll is supposed to be 'not live'...

https://stackoverflow.com/questions/69975232/track-changes-within-dom-element-with-mutationobserver-python/69987634?noredirect=1#comment123721040_69987634

I have a feeling ours will be live. so should be returning node copies instead? It may not be and passing by value so I'll have to check.

If anyone is keen to dev this bit up then take it away. Otherwise will leave as a ticket for now til i get time.

f-string response includes closing tags for void elements

When converting the html object with str and returning it as a response, closing tags for void elements like meta are correctly omitted.

When converting it in an f-string and returning it as a response, closing tags are erroneously included. Example of a simple Sanic route:

@app.route("/404.html")
async def not_found(req: request.Request) -> response.HTTPResponse:
    four_oh_four = html(
        head(
            meta(_charset="utf-8")
        ),
        body(
            h1("Page Not Found"),
            p("Sorry, but the page you were trying to view does not exist."),
        ),
        _lang="en"
    )
    return response.html(f"{four_oh_four}")

which generates the following HTML:

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="utf-8">
		</meta>
	</head>
	<body>
		<h1>Page Not Found</h1>
		<p>Sorry, but the page you were trying to view does not exist.</p>
	</body>
</html>

Note the errant </meta> on line 5. For comparison, the output with return response.html(str(four_oh_four)) is

<html lang="en"><head><meta charset="utf-8" /></head><body><h1>Page Not Found</h1><p>Sorry, but the page you were trying to view does not exist.</p></body></html>

but then I don't get the doctype element.

bug with rendering urls in <a> tags

Howdy. There seems to be some issue rendering the href tag, at least in <a> tags. If you include query parameters it cuts off the link past the ?, if you include https://. See below.

Note, the link does work if put into resulting html correctly (meaning, with the query).

from domonic import a, render

if __name__ == "__main__":

    urls = [
      'example.com/stuff?things=morestuff',
      'https://example.com/stuff?things=morestuff',
      'https://example.com/stuff',
      'https://www.example.com/stuff?thing',
      'https://www.example.com/?stuff'
    ]

    for url in urls:
        print(
            f'''
---------
Renders as: {render(a(_href=url))}
 should be: <a href="{url}"></a>
---------'''
        )

results in the following:

---------
Renders as: <a href="example.com/stuff?things=morestuff"></a>
 should be: <a href="example.com/stuff?things=morestuff"></a>
---------

---------
Renders as: <a href="https://example.com/stuff"></a>
 should be: <a href="https://example.com/stuff?things=morestuff"></a>
---------

---------
Renders as: <a href="https://example.com/stuff"></a>
 should be: <a href="https://example.com/stuff?thing"></a>
---------

---------
Renders as: <a href="https://www.example.com/stuff"></a>
 should be: <a href="https://www.example.com/stuff?thing"></a>
---------

---------
Renders as: <a href="https://www.example.com/"></a>
 should be: <a href="https://www.example.com/?stuff"></a>
---------

feature request: boolean attributes

In HTML5, there are a number of boolean attributes, e.g. async, checked and disabled. It would be nice if these could be recognized and simply output as their short form. Currently, as a workaround, you can give them an empty string or their own name as value, e.g.

_script(_src="foo.js", _async="async")

gives

<script src="foo.js" async="async"/>

but would be nice if we could have

<script src="foo.js" async/>

htmx integration

HeyπŸ‘‹ I'm exploring ways to integrate htmx with domonic. Although the **{"":""} method works just fine, but it tends to result in spaghetti-like code just like React or Vue 😝

Screenshot_20240218_184043

To avoid this, I've worked around. However, the challenge lies in creating custom elements inherited from base elements for inputs, links, buttons, forms, and perhaps divs each one for each one .
here is an example of my simple cutom button:

from domonic import button

class Button(button):
    def __init__(self, text, accent, icon):
        super().__init__(text)
        self.setAttribute("accent", accent)

    def change_accent(self, accent):
        self.setAttribute("accent", accent)

    def htmx_get(self, url: str):
        self.setAttribute("hx-get", url)

    def htmx_post(self, url: str):
        self.setAttribute("hx-post", url)

    def htmx_trigger(self, event: str):
        self.setAttribute("hx-trigger", event)

    def htmx_target(self, target: str):
        self.setAttribute("hx-target", target)

    def htmx_swap(self, swap: str):
        self.setAttribute("hx-swap", swap)

the question, Is there a way to achieve this without having to inherit from each element and create a custom one?
It would be fantastic if domonic had a built-in htmx functions for buttons, inputs, forms, hrefs, or even divs, similar to the div.html() For example:

htmx_button = button('some action').htmx_post('/post').htmx_target('.post')
# or like so
htmx_button = button('some action')
htmx_button.set_hxpost("/post")
htmx_button.set_hxtarget(".post")

You get the point.

cssom

this is in the style.py file at the moment. I semi started it as d3 thing i was doing used some part of it. but I probably wont take that on fully just yet if someone else want it first take it.

slots

I read something about these improving performance but also heard they make your thing immutable. i then figured i could extend a slotted object? and the extended one wouldn't?. i put the placeholders in for slots on the html tag and commented them out for later testing and consideration but stil haven't read and understood enough about them tbh. So this will have to be something I come back to or take advice on.

number utils

I think having a package for utils then having utils for different types of thing is good. obviously preffered if somethign to do with DOM or internets etc. i.e. ip utils maybe. things like that.

unit test and assertion for any existing or new method

If you want to get involved then create an assertion in a unit test for any given method. some are still just print statements at the moment.

this may also uncover bugs. so be prepared.

or create a new unit test for a method that isn't done yet and make it work. good luck

unit tests

I'm bad at these. so any help tightening them up is always appreciated. plus i learn seeing what people do. However be aware changing any prints to assertions you will find bugs.

docstrings

when i first copy and paste method names from MDN page. i just turn the description of the method into a comment then start trying to make them work.

however later we have docstrings that looks like this

def somemethod(x,y,z):
""" some description of the method """

what I'd prefer is they all had proper docstrings and sometimes have been replacing them as I see them. so you will see a mix of both styles in the code. But feel free to help on that effort. they are quite quick to do. as you can auto gen the docstring. then as you start to type a description copilot usually does a semi decent job of finishing it. If you see any docstrings that are done like the example above. just feel free to change them to the proper ones as you go.

linting

whats a good example of a .vscode linting setting.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.