DOM Notation JS
Project description
dnjs
dnjs
is a pure subset of JavaScript
that wants to replace (across many host languages):
- overly limiting/baroque configuration languages
- mucky string based
html
/xml
templating
It is powerful yet familiar, and the reduced syntax makes it easy to implement (the reference implementation in Python
took a couple of days to write) and easy to reason about. Currently the state is very alpha - see the TODO
at the end.
╔══════════════════════════════╗
║ ╔═══════════════╗ ║
║ ║ ╔══════╗ ║ ║
║ ║ ║ JSON ║ dnjs ║ JavaScript ║
║ ║ ╚══════╝ ║ ║
║ ╚═══════════════╝ ║
╚══════════════════════════════╝
Installing the reference interpreter
pip install dnjs
dnjs --help
Examples
Some of these examples reference other files in the examples folder.
For configuration:
import { environments } from "./global.dn.js"
// names of the services to deploy
const serviceNames = ["signup", "account"]
const makeService = (environment, serviceName) => ({
name: serviceName,
ip: environment === environments.PROD ? "189.34.0.4" : "127.0.0.1"
})
export default (environment) => serviceNames.map(
(v, i) => makeService(environment, v)
)
Let's use the reference implementation written in Python
to run these (this also has a Python
API documented below):
dnjs examples/configuration.dn.js examples/environment.json | jq
Gives us:
[
{
"name": "signup",
"ip": "127.0.0.1"
},
{
"name": "account",
"ip": "127.0.0.1"
}
]
For html
templating
dnjs
prescribes functions for making html
, that handily are a subset of mithril (this makes it possible to write powerful, reusable cross-language html
components).
Given the file commentsPage.dn.js
:
import m from "mithril"
import { page } from "./basePage.dn.js"
const commentList = (comments) => m("ul",
comments.map((comment, i) => m("li", `Comment ${i} says: ${comment.text}`))
)
export default (comments) => page(commentList(comments))
Then in a python webserver we can render the file as html
:
from dnjs import render
@app.route("/some-route"):
def some_route():
...
return render("commentsPage.dn.js", comments)
And the endpoint will return:
<html>
<head>
<script src="someScript.js">
</script>
</head>
<body>
<ul>
<li>
Comment 0 says: hiya!
</li>
<li>
Comment 1 says: oioi
</li>
</ul>
</body>
</html>
Or we can use the same components on the frontend with mithril:
import page from "../commentsPage.dn.js"
...
m.mount(document.body, page)
Or we can render the html
on the command line similar to before:
dnjs examples/commentsPage.dn.js examples/comments.json --html
Note, that without the --html
flag, we still make the following JSON
, the conversion to html
is a post-processing stage:
{
"tag": "html",
"attrs": {
"className": ""
},
"children": [
{
"tag": "head",
"attrs": {
...
For css
templating
Using --css
will post-process eg:
export default {
".bold": {"font-weight": "bold"},
".red": {"color": "red"},
}
to:
.bold {
font-weight: bold;
}
.red {
color: red;
}
As a jq
replacement
JSON='[{foo: 1, bar: "one"}, {foo: 2, bar: "two"}]'
echo $JSON | dnjs - -p 'a=>a.map(b=>[b.bar, b.foo])'
[["one", 1], ["two", 2]]
csv
echo $JSON | dnjs - -p 'a=>a.map(b=>[b.bar, b.foo])' --csv
"one",1
"two",2
csv, raw
echo $JSON | dnjs - -p 'a=>a.map(b=>[b.bar, b.foo])' --csv --raw
one,1
two,2
jsonl
(While dnjs
is implemented in python, this is very slow).
JSON='{foo: 1, bar: "one"}\n{foo: 2, bar: "two"}'
echo $JSON | while read l; do echo $l | dnjs - -p 'a=>a.bar' --raw; done
one
two
Flattening
Remember, you can flatten arrays with:
.reduce((a, b)=>[...a, ...b], [])
How exactly does dnjs
extend JSON
?
Remember dnjs
is a restriction of JavaScript
, the aim is not to implement all of it, any more than JSON
is.
Here are all the extensions to JSON
:
- Comments with
//
. - Optional trailing commas.
- Unquoted keys in objects.
import { c } from "./b.dn.js"
,import b from "./b.dn.js"
. Non-local imports are simply ignored (so as to allow importingm
as anything).export default a
,export const b = c
.dict
s andlist
s can be splatted with rest syntax:{...a}
/[...a]
.- Functions can be defined with
const f = (a, b) => c
syntax. Brackets are not required for one argument, functions are called with the number of arguments provided. - Ternary expressions, only in the form
a === b ? c : d
. Equality should be implemented howeverJavaScript
does. - Map, filter, reduce, map over dict, dict from entries, in the form
a.map((v, i) => b)
,a.filter((v, i) => b)
,a.reduce((x, y) => [...x, ...y], [])
,Object.entries(a).map(([k, v], i) => b)
,Object.fromEntries(a)
. - Hyperscript, somewhat compatible with mithril -
m("sometag#some-id.some-class.other-class", {"href": "foo.js", "class": ["another-class"]}, children)
, this evaluates todict
s like{"tag": "sometag", "attrs": {"id": "some-id", className: "some-class other-class another-class", "href": "foo.js", "children": children}
.m.trust(a)
to not escape html. - Multiline templates in the form
`foo ${a}`
,dedent(`foo ${a}`)
.dedent
should work the same as this npm package. - Lists have
.length
,.includes(a)
attributes.
Name
Originally the name stood for DOM Notation JavaScript.
Python
API
These functions return JSON
-able data:
from dnjs import get_default_export, get_named_export
get_default_export(path)
get_named_export(path, name)
This function returns html as a str
:
from dnjs import render
render(path, *values)
The types used throughout dnjs
are fairly simple dataclass
s , there's not much funny stuff going on in the code - check it out!
Development
Install dev requirements with:
pip install -r requirements-dev.txt
Run tests with:
pytest
Pin requirements with:
pip-compile -q; cat requirements.in requirements-dev.in | pip-compile -q --output-file=requirements-dev.txt -
Rebuild and publish (after upversioning) with:
# up version setup.py
rm dist/*; python setup.py sdist bdist_wheel; twine upload dist/*
JS
Javascript validation library to follow - see TODO
section below.
Run tests with:
npm install
npm test
TODO
- Use on something real to iron out bugs.
- Spec out weird behaviour + make the same as js:
- numbers
===
- Nicer docs:
- Write up why we don't need filters like | to_human.
- Consider
onclick
,onkeydown
,on...
functions... and how we want to handle them / attach them on reaching the browser in a isomophic setup. - Decide what else should be added:
- Common string functions like upper case, replace etc?
parseInt
etc..
- Standalone (in
c
/rust
/go
? withPython
bindings) to JSON program. - Write JS library that simply wraps mithril render and has a
dnjs.isValid(path)
function that uses the grammar (doing this may involve removing somelark
-specific bits in the grammar. - Typescript support?
- Consider what prevents
dnjs
from becoming a data interchange format - eg. infinite recursion.--safe
mode? Specify PATHs that it's permitted to import from. - Allow importing JSON using Experimental JSON modules](https://nodejs.org/api/esm.html#esm_experimental_json_modules).
- Remove accidental non-js compatability - eg. template grammar is a bit wacky.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file dnjs-0.0.12.tar.gz
.
File metadata
- Download URL: dnjs-0.0.12.tar.gz
- Upload date:
- Size: 24.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.3.0 pkginfo/1.7.0 requests/2.25.1 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.56.0 CPython/3.8.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 1bcdfa2d8434b2f27aaa5c1d25b36d95ef01f90ff3a2e70495513987416e53bd |
|
MD5 | 2440c24ec00a5249368e440bce315192 |
|
BLAKE2b-256 | 41b7d77c2db77364bf25abc19a108d743438e26313b0373940687fe08afc7090 |
File details
Details for the file dnjs-0.0.12-py3-none-any.whl
.
File metadata
- Download URL: dnjs-0.0.12-py3-none-any.whl
- Upload date:
- Size: 24.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.3.0 pkginfo/1.7.0 requests/2.25.1 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.56.0 CPython/3.8.6
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 562226158ee0b39348963f5f6df54407b48eb0953d4e729eaa11f6a55584fa36 |
|
MD5 | 4b7aa675cf88b6db56e7e3de3da840b5 |
|
BLAKE2b-256 | 7f210c61d955378f9d069d0b6363bcc055f430add201fcebea590132aa84143c |