jondashkyle / nanopage

super handy utilities for traversing flat content state
Apache License 2.0
42 stars 4 forks source link

Wrapper? #5

Open jongacnik opened 6 years ago

jongacnik commented 6 years ago

Curious if we need the wrapper function, instead of just directly exporting the class. Doing this would allow for easy extending:

var Nanopage = require('nanopage')

class Page extends Nanopage {
  formattedDate (state, value) {
    try {
      return someDateFormattingFunction('y-m-d', state.date)
    } catch (err) {
      return false
    }
  }
}

function view (state, emit) {
  var page = new Page(state)
  return html`<div>${page().formattedDate().value()}</div>`
}
jondashkyle commented 6 years ago

yeah 100%! current structure is sort of left over b/c i’m a dummy who can’t architect something without doing it first.

jongacnik commented 6 years ago

This is actually a little bit of a tricky one since we're wanting to return a callable from the constructor. I think we can pull it off though, I'm gonna test something out later today.

jongacnik commented 6 years ago

Took me a sec to track down the pattern I was thinking of. It'd look something like this:

function inherits (ctor, superCtor) {
  ctor.super_ = superCtor
  Object.setPrototypeOf(ctor.prototype, superCtor.prototype)
}

function Nanopage () {
  var instance = function () {
    return instance.__default.apply(instance, arguments)
  }
  instance.__proto__ = Nanopage.prototype
  instance.__ctor.apply(instance, arguments)
  return instance
}

inherits(Nanopage, Function)

// Used to init new Nanopage instance
Nanopage.prototype.__ctor = function (state) {
  this._state = state.content
}

// Used when Nanopage instance is invoked
Nanopage.prototype.__default = function (key) {
  key = key || '/'
  this._value = this._state[key]
  return this
}

// Example method
Nanopage.prototype.value = function (key) {
  return this._value 
}

Usage:

var page = new Nanopage(state)
console.log(page('/').value())

"Extending" Nanopage happens with prototype:

Nanopage.prototype.whatever = function () {
  return 'whatever'
}

This all said, another approach would be to keep Nanopage structure similar how it already is, and to enable a way to pass custom methods into the constructor via opts:

var page = new Nanopage(state, opts)

Or finally, do we even need to worry about extending Nanopage?

jondashkyle commented 6 years ago

oh shit, this is some dark magic. definitely interesting. i like the cleanness of it simply being a class/prototype, but one reason to possibly accept opts like your last example is it plays nicely with the choo plugin, too. for example:

app.use(require('nanopage/choo', opts))

going to think more about the raw class version. ideally we can do something in between the two.