Skip to content

Commit

Permalink
rc
Browse files Browse the repository at this point in the history
  • Loading branch information
metaory committed Aug 19, 2024
1 parent ea1f9dd commit 60e0415
Show file tree
Hide file tree
Showing 13 changed files with 353 additions and 149 deletions.
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "mini-json2html",
"description": "Tiny JSON to HTML Transpiler Library and CLI with Zero dependencies",
"version": "0.0.5",
"name": "html.json",
"description": "HTML DOM tree representation in compact JSON -- Library and CLI",
"version": "0.0.6",
"main": "./dist/index.cjs",
"types": "./dist/index.d.ts",
"module": "./dist/index.mjs",
Expand Down
98 changes: 77 additions & 21 deletions src/transpile.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,89 @@
const LB = '\n'
const TB = '\t'

const foldString = (obj, sep = '&', eq = '=', pre = '') =>
pre +
Object.keys(obj)
.reduce((str, key) => (str += key + eq + obj[key] + sep), '')
.trim()

const foldAttributes = attributes =>
Object.keys(attributes).reduce((acc, cur) => {
const val = attributes[cur]

acc += ` ${cur}="`

switch (val.constructor) {
case String:
acc += val
break
case Object:
acc += foldString(val, '; ')
break
case Array:
acc += foldString(val.at(1), '&', '=', val.at(0))
break
}
acc += '"'
return acc
}, '')

const indent = n =>
Array(n < 0 ? 0 : n)
.fill(TB)
.join('')

export default function (arr) {
let inner = ''
let indent = ''
function walk(nodes) {
let html = ''

function walk(nodes, depth = 0) {
for (const node of nodes) {
const [tag, attributes, val] = node || []
inner += `${indent}<${tag}`
for (const attr in attributes) {
inner += ` ${attr}="${attributes[attr]}"`
const [tag, ...parts] = node || []

if (node.constructor === String) {
html += node
html += LB
continue
}

html += indent(depth)
html += '<'
html += tag

const [attributes = {}] = parts

if (attributes.constructor === Object) {
html += foldAttributes(attributes)
parts.shift()
}

if (!parts.length) {
html += ' />'
html += LB
continue
}
if (val) {
inner += '>'
if (Array.isArray(val)) {
const hasChildren = Array.isArray(val.at(0))
indent += '\t'
inner += '\n'
walk((hasChildren && val) || [val])
indent = indent.replace(/\t$/, '')
inner += `${indent}</${tag}>\n`
} else {
inner += `${val}</${tag}>\n`

html += '>'
html += LB

for (const line of parts) {
if (typeof line !== 'object') {
html += indent(depth)
html += TB
html += line
html += LB
}
} else {
inner += ' />\n'

if (Array.isArray(line)) walk([line], depth + 1)
}

html += indent(depth)
html += `</${tag}>`
html += LB
}
}

walk(arr)

return inner
return html
}
7 changes: 1 addition & 6 deletions src/validate.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,7 @@ export default function (tpl) {
assert.ok(Array.isArray(tpl), 'Array Expected')
assert.ok(tpl.length, 'Empty Array Recieved')

const [root] = tpl
assert.ok(Array.isArray(root), 'Root Is NOT Array')

const [tag, attr] = root
assert.ok(typeof tag === 'string', 'String Expected for Tag')
assert.ok(typeof attr === 'object', 'Object Expected for Attributes')
// assert.ok(typeof attr === 'object', 'Object Expected for Attributes')

return Promise.resolve(tpl)
}
26 changes: 26 additions & 0 deletions test/full.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[
["span", "bare val with no attr"],
["span", "multi bare val with no attr", "moremore"],
["span", { "id": "bWattr" }, "bare value with attr"],
["span", { "id": "multi-bWattr" }, "multi bare value with attr", "morewithtth"],
[
"span",
{ "id": "multi-nested-bWattr" },
"multi bare value with attr",
"morewithtth",
["img", { "src": "zxcy" }, "zz"]
],
[
"div",
{ "align": "center", "class": "wrapper" },
["img", { "src": "example.com" }],
["img", { "src": "google.com" }, "xval"]
],
["footer", ["i", { "class": "icon", "x11": "xorg" }]],
[
"p",
{ "id": "myp" },
["a", { "href": "foobar.com" }, ["p", { "class": "hoge" }, "foo"]],
["i", { "class": "icon", "x11": "xorg" }]
]
]
122 changes: 122 additions & 0 deletions test/preview.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
```
foo
```
<div align="center">
<h1>
HTML.JSON
</h1>
<hr />
<h5>
HTML DOM tree representation in compact JSON
</h5>
<h4>
Library and CLI
</h4>
<h6>
zero dependencies
</h6>
</div>
<h3>
Draft Spec
</h3>
Designed around Array indices
Every element is a new line
Array's first element is the TAG
<br />
Both Attribute and Value can be omitted
<p class="primary">
second element is the attribute object
</p>
<em>
attributes are optional
</em>
<em>
elements
can have
many children
</em>
<em>
every child
is a new line
</em>
values are optional
<b class="opt" />
<div class="wrapper">
elements can
be nested
<span>
arrays as values are children
</span>
<em class="fuga">
nested
</em>
<p>
children can have
<b>
children!
</b>
</p>
</div>
<hr />
Attributes with primitive values are rendered as they are written
<br foo="bar" x11="xorg" />
Attributes with
<em>
Array
</em>
or
<em>
Object
</em>
are treated differently
<br />
<h4>
Attributes with Object as value
</h4>
<div class="wrapper" style="color=indigo; margin=12px;">
default behaviour for any attribute with object as value
is to fold the object with
semicolon as delimiter
and equal sign to delimit keys and values
</div>
<h4>
Attributes with Array as value
</h4>
<a src="https://github.com/search?q=json&type=repositories&p=2&" />
Attributes with array values are querystrings
the first element is a prefix and the following object the query params
<span>
bare val with no attr
</span>
<span>
multi bare val with no attr
moremore
</span>
<span id="bare" class="huh">
bare value with attr
</span>
<span id="multi-bWattr">
multi bare value with attr
morewithtth
</span>
<span id="nested">
next is BIG
<h1>
HEAD
</h1>
</span>
<span id="foo">
okk
<h3>
<p>
deep
</p>
</h3>
<h2>
TITLE
</h2>
</span>
<a href="https://acme.com/search?user=void&org=nada&" />
<button style="color=indigo; margin=12px;" class="btn">
GOGO
</button>
22 changes: 22 additions & 0 deletions test/preview.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import {
readFile,
writeFile
} from 'node:fs/promises'
import transpile from '../src/transpile.js'
import validate from '../src/validate.js'


const content = JSON.parse(await readFile('./test/preview.json', { encoding: 'utf8' }))
const write = data => writeFile('./test/preview.html', data)

console.log('content', '::', content, '<<<::')

validate(content)
.then(transpile)
.then(write)
.then(console.log)
.catch(console.error)

// validate(content).then(transpile).then(write).then(console.log).catch(console.error)

// log(transpile([['div', { zzz: 9898 }, 'foo']]))
Loading

0 comments on commit 60e0415

Please sign in to comment.