npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

nunjucks-pagelet

v2.1.0

Published

scrat-swig的nunjucks版本, 提供pagelet支持

Downloads

9

Readme

scrat 后端渲染解决方案的模板扩展

scrat后端渲染组件化开发模式通过扩展 nunjucks 模板引擎实现了组件资源管理方案。

NPM Version Build Status

用法

const path = require('path');
const nunjucks = require('nunjucks');
const pagelet = require('nujucks-pagelet');

const baseDir = path.join(process.cwd(), './test/fixtures/general');
const env = nunjucks.configure(baseDir, {});

/**
 * 初始化入口
 * @method Engine#register
 * @param {Object} opt 配置对象
 * @param {String|Object|Function} opt.manifest 资源映射表, 可以是文件路径/映射表对象/读取函数
 * @param {String} opt.root 静态文件的根目录
 * @param {Boolean} [opt.cache] 是否缓存资源映射表
 * @param {Object} [opt.logger] 日志对象
 * @return {void}
 */
pagelet.configure({
  root: baseDir,
  manifest: path.join(baseDir, 'manifest.json'),
  cache: true
});

// 注册 Tag 到 nunjucks
pagelet.register(env);

// 渲染
const locals = {};
const html = env.render('test.tpl', locals);

// use in express
const express = require('express');
const app = express();
app.set('view engine', 'tpl');
env.express(app);

// 注册中间件, 读取 Pagelet 的参数
app.use(function(req, res, next) {
  res.locals._query = req.query;
  res.locals._body = req.body;
  var pagelets = req.get('X-Pagelets');
  if(pagelets){
      res.set('Content-Type', 'application/json');
      // res.set('Cache-Control', 'no-cache, no-store');
      // res.set('Pragma', 'no-cache');
      // res.set('Expires', 0);
      res.locals._pagelets = pagelets;
  }
  next();
});

app.get('/', function(req, res) {
  res.render('test.tpl', res.locals);
});

资源依赖表

manifest 文件是通过构建工具生成的, 主要描述了资源的依赖关系.

{
  "combo": false,
  "comboPattern": "/co??%s",
  "hash": "f0ab3c",
  "res": {
    "components/nav/nav.js": {
      "uri": "c/nav/nav.js",
      "type": "js",
      "deps": [
        "views/jquery/jquery.js",
        "components/nav/nav.css"
      ]
    },
    "components/nav/nav.css": {
      "uri": "c/nav/nav.css",
      "type": "css",
      "deps": [
        "views/reset/reset.css"
      ]
    },
    "components/bar/bar.tpl": {
      "uri": "c/bar/bar.tpl",
      "type": "tpl",
      "deps": [
        "nav",
        "components/bar/bar.css"
      ]
    },
    "components/bar/bar.css": {
      "uri": "c/bar/bar.css",
      "type": "css"
    },
    "components/foo/foo.tpl": {
      "uri": "c/foo/foo.tpl",
      "type": "tpl",
      "deps": [
        "nav",
        "components/foo/foo.css"
      ]
    },
    "components/foo/foo.css": {
      "uri": "c/foo/foo.css",
      "type": "css"
    },
    "views/jquery/jquery.js": {
      "uri": "v/jquery/jquery.js",
      "type": "js"
    },
    "views/reset/reset.css": {
      "uri": "v/reset/reset.css",
      "type": "css"
    },
    "views/index/index.tpl": {
      "uri": "views/test.tpl",
      "type": "tpl",
      "deps": [
        "foo"
      ]
    }
  }
}

新增规则

  • nunjucks 的自定义标签语法进行了修订:

    • 属性分隔符增加对空格的支持, 原逗号仍保留支持, 但建议使用空格
    • data-src="http://" 这类的属性名, 无需双引号包裹
    • disabled 这类的没有赋值的属性, 还是维持官方的实现, 需要双引号包裹, 否则会当做变量
    • 示例:
      • {% body cdn="asd", data-src="http://", "disabled"" %}{% endbody %}
      • {% pagelet $id="asd" class=["a", "b"] style={a: true, b: someVar} %}{% endpagelet %}
  • swig版本传送门: scrat-swig, Base on Latest commit 6cdcb1f on 20 Oct .

新增模板标签

require

  • 功能: 资源/组件引用接口,调用后只是收集资源,并不会有内容输出。

  • 闭合: NO

  • 参数:

    • $id: 字符串或模板变量。要引用的组件id或相对路径
    • $scope: 可选, 隔离上层变量, 仅在属性上设置的才传递进去
    • 其他参数: 作为子组件的局部变量, 继承并覆盖上层变量
  • 示例:

    {% require $id="header" %}    {# 组件id #}
    {% require $id="./lib.js" %}  {# 工程路径 #}
    {% for val in obj %}
      {% require $id=val %}     {# 模板变量 #}
    {% endfor %}

html

  • 功能: 替代原生的 <html> 标签包裹页面主体部分,用于实现资源url输出时替换页面占位

  • 闭合: YES

  • 参数:

    • cdn: 指定pagelet加载时所用的域名,可以是字符串字面量,也可以是模板变量
    • doctype: 声明 doctype , 默认为 html
    • 任何其他参数都将转换为输出的html标签的属性。
  • 示例:

    {% html class="abc" data-value="bcd" %}
      ...
    {% endhtml %}

    渲染后的html:

    <!DOCTYPE html>
    <html class="abc" data-value="bcd">
      ...
    </html>

head

  • 功能: 替代原生的 <head> 标签包裹页面head部分,用于实现资源CSS输出占位

  • 闭合: YES

  • 参数: 任何参数都将转换为输出的 head 标签的属性。

  • 示例:

    {% html%}
      {% head class="abc" data-xxx="bcd" %}
        ...
      {% endhead %}
      ...
    {% endhtml %}

    渲染后的html:

    <html>
      <head class="abc" "data-xxx"="bcd">
        ...
      </head>
      ...
    </html>

body

  • 功能: 替代原生的 <body> 标签包裹页面body部分,用于实现资源JS输出占位

  • 闭合: YES

  • 参数: 任何参数都将转换为输出的 body 标签的属性。

  • 示例:

    {% html%}
      {% head %}
        ...
      {% endhead %}
      {% body class="main" id="main" "data-ooo"="abc" %}
        ...
      {% endbody %}
    {% endhtml %}

    渲染后的html:

    <html>
      <head>
        ...
      </head>
      <body class="main" id="main" data-ooo="abc">
        ...
      </body>
    </html>

script

  • 功能: 替代原生的 <script> 标签,收集页面中散落的 script 脚本统一放到页面尾部输出。

  • 闭合: YES

  • 参数: 无

  • 示例:

    {% html%}
      {% head %}
        ...
        {% require $id="../lib/jquery.js" %}  {# 引用资源 #}
      {% endhead %}
      {% body %}
        ...
        {% script %}
          var header = require('header');
          header.init();
        {% endscript %}
        {% require $id="./index.js" %}  {# 引用资源 #}
      {% endbody %}
    {% endhtml %}

    渲染后的html:

    <html>
      <head>
        ...
      </head>
      <body>
        ...
        <script src="/views/lib/jquery.js"></script>
        <script src="/views/index/index.js"></script>
        <script>
          !function(){
            var header = require('header');
            header.init();
          }();
        </script>
      </body>
    </html>
  • 注意: 在body闭合标签之前,js输出的顺序是:

    1. require标签加载的外链js
    2. script标签收集的内联js

pagelet

  • 功能: 页面区域划分,用于 quickling 加载页面

  • 闭合: YES

  • 注意: pagelet默认会生成一个dom结构,如果希望不生成任何结构,须设置 $tag 属性值为字符串 "none"

  • 参数:

    • $id: 字符串|模板变量。定义pagelet的id
    • $tag: 字符串|模板变量|"none"。要生成的占位标签的标签名,可以不指定,默认是 div。如果指定为none,框架会输出一个注释来标注pagelet的范围。
    • 任何其他参数都将转换为输出的pagelet占位标签的属性。
  • 示例:

    {% html%}
      {% head %}
        ...
      {% endhead %}
      {% body %}
        ...
        {% pagelet $id="main" class="main" %}
          <ul>
            {% pagelet $id="list" $tag="none" %}
              {% for item in list %}
              <li>{{ loop.index }} - {{ loop.key }}: {{ x }}</li>
              {% endfor %}
            {% endpagelet %}
          </ul>
          {% pagelet $id="form" $tag="form" id="my-form" class="form-control" %}
            <input type="text" name="username">
          {% endpagelet %}
        {% endpagelet %}
        ...
      {% endbody %}
    {% endhtml %}

    渲染后的html:

    <html>
      <head>
        ...
      </head>
      <body>
        ...
        <div class="main" data-pagelet="main">
          <ul>
            <!-- pagelet [main.list] start -->
            <li>0 - a: 123</li>
            <li>0 - b: 456</li>
            <!-- pagelet [main.list] end -->
          </ul>
          <form id="my-form" class="form-control" data-pagelet="main.form">
            <input type="text" name="username">
          </form>
        </div>
        ...
      </body>
    </html>

title

  • 功能: 如果使用 quickling 切换页面,你的页面此标签替代原生的 <title> 标签用以收集页面标题数据,这样页面切换后框架可以自动修改页面的title显示。

  • 闭合: YES

  • 参数: 无

  • 示例:

    {% html%}
      {% head %}
        ...
        {% title %}首页{% endtitle %}
      {% endhead %}
      {% body %}
        ...
      {% endbody %}
    {% endhtml %}

    渲染后的html:

    <html>
      <head>
        ...
        <title>首页</title>
      </head>
      <body>
        ...
      </body>
    </html>

datalet

  • 功能: 在pagelet区域内收集模板数据将来在 quickling 加载时可以传递给前端框架。

  • 闭合: NO

  • 示例:

    {% html%}
      {% head %}
        ...
        {% title %} 列表页 - 第{{ offset }}页 {% endtitle %}
      {% endhead %}
      {% body %}
        ...
        {% pagelet $id="main" class="main" %}
          {% pagelet $id="list" $tag="ul" %}
            {% for item in list %}
            <li>{{ loop.index }} - {{ loop.key }}: {{ x }}</li>
            {% endfor %}
            {% datalet page=offset %}
          {% endpagelet %}
        {% endpagelet %}
        ...
      {% endbody %}
    {% endhtml %}

    假设前端获取main.list的pagelet数据:

    {
      "title": "列表页 - 第5页",   // title收集
      "html": {
        "main.list": "..."      // pagelet的html内容
      },
      "data": {
        page: 5                 // datalet收集
      },
      "js": [ ... ],            // js依赖
      "css": [ ... ],           // css依赖
      "script": [ ... ]         // script收集
    }

ATF

  • 功能: 收集位于 ATF 标签以上的css资源,并内嵌到主文档的head标签中。只会收集使用 require 标签加载的css资源,并不会收集link标签的css资源。用于加快首屏渲染速度的优化。

  • 闭合: NO

  • 参数: 无

  • 示例:

    {% html%}
      {% head %}
        ...
      {% endhead %}
      {% body %}
        ...
        {% require $id="header" %}
        {% require $id="./index.css" %}
        {% ATF %}
        {% require $id="footer" %}
        ...
      {% endbody %}
    {% endhtml %}

    渲染后的html:

    <html>
      <head>
        ...
        <style>
          .header {...}
          .index {...}
        </style>
      </head>
      <body>
        ...
        <link rel="stylesheet" href="/co??c/footer/footer.css" data-defer>
        ...
      </body>
    </html>