Skip to content

Examples

aMarCruz edited this page Dec 28, 2018 · 6 revisions

Basic usage

//#set _VAR2 = 1

//#if _VAR1
console.log('var1')
//#elif _VAR2
console.log('var2')
//#else
  //#error 'Please set _VAR1 or _VAR2'
//#endif

Result:

console.log('var2')

Simple Replacement

//#set _FOO = 'foo'

let bar = '$_FOO'.toUpperCase()
let baz = { $_FOO: 'bar' }

console.log('$_FOO')
console.log(baz['$_FOO'])
console.log(baz.$_FOO)

Result:

let bar = 'foo'.toUpperCase()   // bar = 'FOO'
let baz = { foo: 'bar' }        // baz = { foo: 'bar' }

console.log('foo')              // ⇒ 'foo'
console.log(baz['foo'])         // ⇒ 'bar'
console.log(baz.foo)            // ⇒ 'bar'

Object and Properties

//#set _OBJ = { prop: 1 }
console.log($_OBJ.prop)
console.log($_OBJ)
console.log($_OBJ.foo)

Result:

console.log(1)                    // ⇒ 1
console.log({"prop":1})           // ⇒ '{prop: 1}'
console.log(undefined)            // ⇒ 'undefined'

Making your linter happy

//#set _NUM = 10
//#set _STR = 'foo'
//#if 0
const $_NUM = 10
// no need to declare $_STR as this is inside quotes
//#endif
let n = $_NUM
let s = '$_STR'

Result:

let n = 10
let s = 'foo'

CoffeeScript

Use the prefixes option with ['# ', '### '] for CoffeeScript linters:

# #set _DEBUG = true

### #if _DEBUG
console.log "debug mode"
### #else //###
console.log "production"
# #endif

Result:

console.log "debug mode"

Note: The '//###' following the ### #else is for syntax highlighters, the CoffeeScript compiler (and jscc) are happy without this.

HTML

The starting sequence of HTML comments is a predefined prefix, but you need the '//' before the '-->'.

<!--#set _DEBUG = 1 //-->
<!--#set _TITLE = 'My App' //-->
<!--#set _SUFFIX = new Date().toISOString().replace(/\D/, '').substr(0, 14) //-->
<!DOCTYPE html>
<!--
  $_TITLE
  @license MIT
-->
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>$_TITLE</title>
</head>
<body>
  <!--#if _DEBUG //-->
  <script src="js/debug.js?$_SUFFIX"></script>
  <!--#else -->
  <script src="js/release.js?$_SUFFIX"></script>
  <!--#endif -->
</body>
</html>

Result:

<!DOCTYPE html>
<!--
  My App
  @license MIT
-->
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>My App</title>
</head>
<body>
  <script src="js/debug.js?201610120518"></script>
</body>
</html>

Performance Gains

Assume you have this src/_types.js file:

// src/_types.js
export default {
  TAG: 1,
  TEXT: 3,
  COMMENT: 8
}

...this fragment in parser.js:

//#set _DATE = new Date().toISOString().slice(0, 10)
/*
  yat-amazing-parser v$_VERSION
  File: $_FILE
  Date: $_DATE
*/
//#if !_T
// fallback to import _types.js
import $_T from './_types'
//#endif

// ...amazing code...

function parse () {
  switch (this.type) {
    case $_T.TAG: this.parseTag()
      break
    case $_T.TEXT: this.parseText()
      break
    case $_T.COMMENT: this.parseComment()
      break
  }
}

...and you are using rollup with rollup-plugin-jscc and this config:

// rollup.config.js
import jscc from 'rollup-plugin-jscc'
import types from 'src/_types'

export default {
  entry: 'src/parser.js',
  plugins: [
    jscc({ values: { _T: types } })
  ]
}

make the hard part:

rollup -c -o dist/parser.js

As a result of your efforts, you've won this clean, beautiful and performant code:

/*
  yat-amazing-parser v1.0
  File: src/parser.js
  Date: 2016-09-23
*/

// ...amazing code...

function parse () {
  switch (this.type) {
    case 1: this.parseTag()
      break
    case 3: this.parseText()
      break
    case 8: this.parseComment()
      break
  }
}

* _VERSION is a predefined varname, new in jscc v0.2.1

Hidden Blocks

ES6 imports can't be declared conditionally, but with JSCC it is possible!

//#if process.env.BROWSER
import mylib from 'browser-lib'
//#else
import mylib from 'node-lib'
//#endif

mylib.doSomething()

...Ops! this code generate issues with linters and syntax highlighters, but using JS multiline comments you can rewrite your code like this:

/*#if process.env.BROWSER
import mylib from 'browser-lib'
//#else */
import mylib from 'node-lib'
//#endif

mylib.doSomething()

Result:

import mylib from 'browser-lib'

mylib.doSomething()

...if "BROWSER" is defined in the node.js environment (yes, process.env is accesible to expressions).

Note:

The line '//#else */' don't requires other '//' before '*/' because any text after #else and #endif is discarded.

Hiding Debugging Output

This is a nice trick:

//#if _DEBUG
//#set _DEBUGOUT = 'console.log'
//#elif 0
const $_DEBUGOUT = console.log // for linters
//#else
//#set _DEBUGOUT '//'
//#endif

$_DEBUGOUT('Ops!')

Result with _DEBUG:

console.log('Ops!')

Result without _DEBUG:

//('Ops!')

😃