)
}
}
)
(
}
{
)
)
(
)
(
(
{
}
)
(
)
}
)
)
{
(
(
)
)
}
)
(
}

Speed Coded HTML Templating Thoughts

  1. const tmpl = `
  2.   main
  3.     h1 Welcome
  4.     hr
  5.     nav
  6.       button one
  7.       button two
  8.       button three
  9.     hr
  10.     p this is a test
  11.     p this is another test
  12.     textarea hello
  13.     ul 
  14.       li alpha
  15.       li beta
  16.       li zeta
  17.         ul 
  18.           li organize
  19.           li things
  20.       li and stuff
  21.   hr
  22.   footer 2022
  23. `
  24.  
  25. let htm = parse(tmpl);
  26. document.body.innerHTML += htm
  27. console.log(htm)
  28.  
  29. function isTag(tag) { 
  30.   return !/Unknown/.test(document.createElement(tag) + '')
  31. }
  32.  
  33. function parse(input) {
  34.   let lines = input.split(/\n/)
  35.   let html = []
  36.   let closeTags = []
  37.   let lastIndent = 0;
  38.  
  39.   for (let i = 1; i < lines.length; i++) {
  40.     let indent = 0;
  41.     let tag = '';
  42.     let content = ''
  43.     let line = lines[i]
  44.     let mode = 'start';
  45.  
  46.     for (let j = 0; j < line.length; j++) {
  47.       const char = line[j]
  48.       if (char == ' ' && mode === 'start') {
  49.         indent++;
  50.       } else if (char != ' ' && mode != 'content') {
  51.         mode = 'tag'
  52.         tag += char
  53.       } else {
  54.         mode = 'content'
  55.         content += char;
  56.       }
  57.     }
  58.  
  59.     if (indent <= lastIndent && closeTags.length > 0) {
  60.         let back = lastIndent
  61.         while(back >= indent) {
  62.           html.push(closeTags.pop())
  63.           back -= 2
  64.         }
  65.     }
  66.  
  67.     if (tag.length > 0) { 
  68.       let xtra = ''
  69.       let origTag = tag; 
  70.  
  71.       if (!isTag(tag)) {
  72.         tag = 'div'
  73.         xtra = ` class="${origTag}" `
  74.       }
  75.       closeTags.push(`</${tag}>`)
  76.       html.push(`<${tag + xtra}>`)
  77.       if (content.length > 0) html.push(content)
  78.     }
  79.  
  80.     lastIndent = indent;
  81.   }
  82.  
  83.   return [...html, ...closeTags.reverse()].join('')
  84. }

Parse a minimalistic html template inspired by the likes of jade, haml, pug etc… This is very speed-coded. I may revisit the same thing with a bit more of an elegant approach in the future.

// html // javascript // strings // ui

Check if HTML Tag is Valid

  1. const isTag = tag => { 
  2.   return !/Unknown/.test(document.createElement(tag) + '')
  3. }
  4.  
  5. console.log('section:', isTag('section'))
  6. console.log('div:', isTag('div'))
  7. console.log('nav:', isTag('nav'))
  8. console.log('banana:', isTag('banana'))

Check if a tagName is a valid html element.

When casting a dom node to a string, you’ll get a class name like this:

  1. document.createElement('div') + ''
  2. // '[object HTMLDivElement]'
  3.  
  4. // you can cast to a string with `toString` if 
  5. // you want things to be more readable
  6. document.createElement('section').toString()
  7. // '[object HTMLElement]'
  8.  
  9. document.createElement('input') + ''
  10. // '[object HTMLInputElement]'

When you try to create something with an unknown tagName you’ll end up with:

  1. document.createElement('banana') + ''
  2. // '[object HTMLUnknownElement]'

So, testing for the presence of the string Unknown is an easy way to check if a tagName is valid in a given browser. This is the perfect kind of thing to memoize:

  1. const tags = {}
  2. const isTag = tag => { 
  3.   if (tags[tag] != null) {
  4.     // already calculated
  5.     console.log('loking up: ', tag, tags[tag]);
  6.     return tags[tag]
  7.   }
  8.   const result = !/Unknown/.test(document.createElement(tag) + '')
  9.   tags[tag] = result
  10.   return result
  11. }
  12.  
  13. console.log('calculator', isTag('calculator'))
  14. console.log('calculator', isTag('calculator'))
  15.  
  16. console.log('strong', isTag('strong'))
  17. console.log('strong', isTag('strong'))
// dom // html // javascript // regex // strings // tricks // ui

Remove First Line of a String

  1. str.replace(/.*/, '').substr(1)

Needed this one today…

Tab Timer

  1. <title id=t></title>
  2. <script>
  3.   st = Date.now()
  4.   setInterval(_ => {
  5.     s = Date.now() - st
  6.     t.innerHTML = 
  7.       ~~(s/6e4)+':'+(~~(s/1e3)%60)
  8.   }, 500)
  9. </script>

I speed coded this recently to put a timer in a brower tab.

Have a look at it here in a new tab…

Obviously this is pretty odd – but it does work for my purposes 😉

Gravity Dots 2

  1. d = document
  2. b = d.body
  3. b.style.margin = 0
  4. b.style.background = 'black'
  5. r = (v = 1) => Math.random() * v
  6.  
  7. with(
  8.   b.appendChild(
  9.     d.createElement`canvas`
  10.   ).getContext`2d`) {
  11.  
  12.   onresize = () => {
  13.     canvas.width = innerWidth
  14.     canvas.height = innerHeight
  15.   }
  16.   onresize()
  17.  
  18.   fillStyle = 'red'
  19.  
  20.   dot = (
  21.     x = r(innerWidth),
  22.     y = 0,
  23.     mass = 20, sr = r(2) + 2, 
  24.     R = sr,
  25.     dx, dy,
  26.     col = '#005eb0',
  27.     dist, vx = .2, vy = 0) => { 
  28.  
  29.     return () => { 
  30.       fillStyle = col
  31.       R = sr
  32.       if (r() < .001) {
  33.         vx = r() * 4 - 2
  34.         R = sr * 2
  35.         fillStyle = 'red'
  36.         col = `hsl(${r(360)}deg, 50%, 50%)`
  37.       }
  38.  
  39.       dx = innerWidth / 2 - x
  40.       dy = innerHeight / 2 - y
  41.       dist = Math.sqrt(dx * dx + dy * dy)
  42.       dist *= dist
  43.       vx += dx / dist * mass
  44.       vy += dy / dist * mass
  45.  
  46.       x += vx
  47.       y += vy
  48.  
  49.       beginPath()
  50.       arc(x, y, R, 0, 6.29)
  51.       fill()
  52.     }
  53.   }
  54.  
  55.   const dots = []
  56.   for (let i = 0; i < 100; i++) dots.push(dot())
  57.   loop = () => {
  58.     fillStyle = 'rgba(0, 0, 0, 0.05)'
  59.     fillRect(0, 0, canvas.width, canvas.height)
  60.     dots.map(d => d())
  61.   }
  62.   setInterval(loop, 16)
  63. }

A variation on this recent post.

snippet.zone ~ 2021-24 /// {s/z}