Rationalize calling interface to pass only root, dirname is implied by pathname
authorNick Downing <nick@ndcode.org>
Fri, 16 Nov 2018 13:16:57 +0000 (00:16 +1100)
committerNick Downing <nick@ndcode.org>
Fri, 16 Nov 2018 13:16:57 +0000 (00:16 +1100)
README.md
jst.js
package.json

index 832dafa..c00c277 100644 (file)
--- a/README.md
+++ b/README.md
@@ -4,8 +4,8 @@ An NDCODE project.
 
 ## Overview
 
-The `jst` package exports a single function `jst(root, dirname, pathname)`,
-which loads the given file from disk, parses it for a superset of JavaScript
+The `jst` package exports a single function `jst(pathname, root, args)`,
+which loads a file `pathname` from disk, parses it for a superset of JavaScript
 (ES6) which can contain HTML-like constructs, and then generates equivalent
 plain JavaScript code which in turn, can generate the desired HTML.
 
@@ -233,13 +233,49 @@ A slight difference between CommonJS exports and JavaScript template exports,
 is that where CommonJS modules set the dedicated symbol `module.exports` to
 whatever is exported, JavaScript templates instead `return` what is exported.
 
+## Template paths and variables
+
+Similarly to CommonJS, the variable `_require` is injected by the system and is
+available to all templates. Other variables injected by the system are
+`_pathname` which is the path to the currently executing template, and `_root`
+which is the root directory for absolute pathname references in `_require()`.
+
+Thus, paths sent to `_require()` are resolved relative to either `_root` if
+absolute (beginning with `/`) or the directory part of `_pathname` if relative
+(not beginning with `/`). Each template gets its own `_require()` function,
+which knows the `_pathname` and `_root` values of the calling template.
+
+If further variables should be made available to the template, they can be
+included as a dictionary in the `args` parameter to `jst()`. For example,
+```js
+let template = jst(
+  '/home/myname/www/blog/page.jst',
+  '/home/myname/www',
+  {myvar: 'some value'}
+)
+```
+parses and executes the template `/home/myname/www/blog/page.jst`, with the
+variables `_pathname` set to `'/home/myname/www/blog/page.jst'`, `_root` set to
+`'/home/myname/www'`, and `myvar` set to `'some value'`. Suppose this contains
+```js
+let footer = _require('/site/footer.jst')
+```
+or
+```js
+let footer = _require('../site/footer.jst')
+```
+then the template `/home/myname/www/site/footer.jst` is parsed and executed,
+with `_pathname` set to `'/home/myname/www/site/footer.jst'` and the other
+injected variables `_root` and `myvar` set from the original call to `jst()`.
+
 ## Multi-part template examples
 
 ### Templating with HTML text strings
 
-Here is an example of a template which takes some text and wraps it in the
-standard HTML tags to create a page. Many templating systems work like this,
-so that you can put standard scripts, viewport commands etc, in one place.
+Here is an example of a template which takes the body of a page (as text which
+may contain HTML tags), and wraps it in the standard `html` and `body` tags to
+create a complete page. The idea is to use this to generate every page, so that
+additional commands, such as viewport commands or script tags, can be set here.
 
 Save this as `page.jst`, since it's the template for all pages in the system:
 ```
@@ -391,11 +427,6 @@ translator to remove the need for some quoting or backticking workarounds, and
 to improve support for some HTML constructs such as stylesheets via a dedicated
 CSS parser, and similarly we may add various preprocessors such as TypeScript.
 
-We may also simplify the API to take only the root directory and the pathname.
-With the current interface, the working directory name and the pathname are
-resolved before doing anything, so the caller should really do this. It evolved
-that way because of the implementation details of the `_require(...)` pathway.
-
 We're also working on a "JSTizer" which can take ordinary HTML code and spit
 out sample JST code, which is handy during development when inserting things
 like Bootstrap templates into your page. The primary interface to the JSTizer
diff --git a/jst.js b/jst.js
index d7474a5..ef28e44 100644 (file)
--- a/jst.js
+++ b/jst.js
@@ -36,23 +36,25 @@ let fs_stat = util.promisify(fs.stat)
 let fs_writeFile = util.promisify(fs.writeFile)
 
 let build_cache = new BuildCache()
-let jst = async (root, dirname, pathname, args) => {
-  while (pathname.charAt(0) === '/') {
-    dirname = root
-    pathname = pathname.slice(1)
-  }
-  pathname = path.posix.resolve(dirname, pathname)
+let jst = async (pathname, root, args) => {
+  let dirname = path.posix.dirname(pathname)
   return build_cache.get(
     pathname,
     async result => {
-      dirname = path.posix.dirname(pathname)
-
-      let arg_names = ['_require', '_html_escape', '_root', '_dirname']
+      let arg_names = ['_require', '_html_escape', '_pathname', '_root']
       let arg_values = [
-        async pathname => jst(root, dirname, pathname, args),
+        async pathname => {
+          let temp = dirname
+          while (pathname.charAt(0) === '/') {
+            temp = root
+            pathname = pathname.slice(1)
+          }
+          pathname = path.posix.resolve(temp, pathname)
+          return jst(pathname, root, args)
+        },
         html_escape,
-        root,
-        dirname
+        pathname,
+        root
       ]
       if (args !== undefined)
         for (let i in args)
index f20ca52..65d7578 100644 (file)
@@ -1,6 +1,6 @@
 {
   "name": "@ndcode/jst",
-  "version": "0.1.0",
+  "version": "0.1.2",
   "description": "JavaScript Templates for HTML.",
   "keywords": [
     "template",