2.2.0 • Published 6 years ago

@scoutgg/fn-pug v2.2.0

Weekly downloads
1
License
ISC
Repository
github
Last release
6 years ago

fn-pug

Create a virtual dom producing function from pug templates

Installation

$ npm i scoutgg/fn-pug

Usage

Browserify

{
  "browserify": {
    "transform": [
      "fn-pug/lib/transform/browserify"
    ]
  }
}

Standalone (Node)

const fnPug = require('fn-pug')

const template = "h1 hello ${name}"

const { code, map, ast } = fnPug(template)

console.log(code)

Standalone (Browser)

const fnPug = require('fn-pug')
const { h, create } = require('virtual-dom')

const runtime = require('fn-pug/lib/runtime/vdom')
const vdomRuntime = runtime.default(h)

const template = "h1 hello ${name}"

const greeter = fnPug.compileClient(template, vdomRuntime)

const vNodes = greeter.call({ name: 'FireNeslo' })
const domNodes = vNodes.map(create)

for(const node of domNodes) {
  document.body.appendChild(node)
}

Syntax

for the most part what is documented on the pug website will work with a few exeptions like extends or include

Special syntax

There is also some added special syntax

Event listeners

button((click)=console.log(e))

you can add event listeners using (eventName). They will work like arrow functions with the magical variable e that represents the event.

Properties

input([value]="Some value")

Assigns value to the dom elements property instead of attribute.

Properties also pass values by reference instead of serializing.

For custom elements this can also trigger setters

Bindings

form-control([(value)]=this.input)

Syntactic sugar for

form-control(
  [value]=this.input, 
  (valueChanged)=this.input=e.target.value
)

Allows you to create nice declarative databinding

Refs

video(#video, src="some.video")

button((click)=video.play()) Play

Creates reference names for nodes

Hooks

.wrapper(*modify=node => console.log(node))

Provides hooks for manipulating native dom node.

Example hook

function logNode(prefix) {
  return function connect(node) {
    console.log(prefix, 'connect', node)

    return function disconnect() {
      console.log(prefix, 'disconnect', node)
    }
  }
}
.wrapper(*log=logNode('inner'))

Mixins

This is the intended pattern for partials and minimal components

Usage
- const partial = require('./partial.pug')

+partial(class="important")
  h1 This is important
Definition
// partial.pug
.partial(class=properties.class)
  each child in children
    .wrapped
      = child

API

fnPug(code, options)

Compile pug strings

Returns

  • Result result compilation result
  • Program result.ast babel ast output
  • SourceMapGenerator result.map Sourcemap builder
  • string result.code javascript output

Params:

  • string code - The pug to compile
  • object options - Compilation options
  • string options.file - Template filename
const fnPug = require('fn-pug')

const template = 'h1 hello'

const { code, map, ast } = fnJade(template, {
  file: 'greeting.pug'
})

fnPugify(file, options)

Browserify pug transform

Returns

Params:

  • string file - Template filename
  • object options - Compilation options
  • string[] options.extensions - list of pug template extensions
  • string options.runtime - runtime to embed ["dom", "string", "virtual-dom", "snabbdom", "react", "vue"]
const fs = require('fs')
const browserify = require('browserify') 
const fnPugify = require('fn-pug/lib/transform/browserify')

// this is what will be passed if you pass no options
const defaultOptions = {
  runtime: "virtual-dom",
  extensions: [".jade", ".pug"],
}

const bundle = browserify('main.js')
  .transform(fnPugify, defaultOptions)
  .bundle()
  .pipe(fs.createWriteStream('bundle.js'))
{
  "browserify": {
    "transform": [
      ["fn-pug/lib/transform/browserify", {
        "runtime": "virtual-dom",
        "extensions": [".jade", ".pug"]
      }]
    ]
  }
}

Runtime

If you want to build or extend the runtime you can build you own.

import { PugRuntime } from 'fn-pug/lib/runtime'

// all methods have defaults

export class MyRuntime extends PugRuntime {
  constructor(options) {
    // set options
  }
  create(tagName) {
    // create reference node
  }
  child(parentRef, nodeRef) {
    // append child node
  }
  events(nodeRef, events = [ [ "name", () => callback() ] ]) {
    // add event listeners
  }
  element(nodeRef) {
    // create element from reference
  }
  hooks(nodeRef, hooks = { hookName: hookValue }) {
    // register hooks
  }
  handles(nodeRef, templateContext, handleName) {
    // register handle for handleName
  }
  props(nodeRef, properties) {
    // set properties for reference 
  }
  text(text) {
    // create text node
  }
  attrs(nodeRef, attrs) {
    // set attributes for reference 
  }
  attr(value) {
    // normalize attribute 
  }
  mixin(context, nodeRef, ...props) {
    // include mixin template
  }
  each(iterable, callback) {
    // iterator implementation
  }
  end(result) {
    // transform return value
  }
}

export default function createRuntime(options) {
  return new MyRuntime(options)
}