jdists 一款强大的代码块预处理工具

jdists 强大的代码块预处理工具

Build Status
NPM version

jdists logo

背景

软件发布流程

code pretreatment

通常软件发布时会将源文件做一次「预处理」再编译成可执行文件,才发布到市场。

「预处理」的目的主要是出于以下几点

  • 配置线上运行环境,如调试服务地址需变更为实现线上地址;
  • 减少执行程序的大小,移除没有使用的代码或资源并压缩;
  • 增加逆向工程的成本,给代码做混淆(包括改变标识符和代码结构),降低可读性;
  • 移除或增加调试功能,关闭或开启一些特权后门。

一些 IDE 已在「编译」时集成了「预处理」功能。

什么是 jdists

jdists 是一款强大的代码块预处理工具。

什么是「代码块」(code block)?

通常就是注释或注释包裹的代码片段,用于表达各种各样的含义。

举个栗子

  • TODO 注释,表示代码中待完善的地方
/* TODO 功能待开发 */

  • wiredep 注释,表示引入 bower 组件依赖的 css 资源
  <!-- bower:css -->
  <link rel="stylesheet" href="bower_components/css/bootstrap.css" />
  <!-- endbower -->

  • jshint.js 顶部注释,表示版权声明
/*!
 * JSHint, by JSHint Community.
 *
 * This file (and this file only) is licensed under the same slightly modified
 * MIT license that JSLint is. It stops evil-doers everywhere:
 *
 *   Copyright (c) 2002 Douglas Crockford  (www.JSLint.com)
 * .........
 */

  • jshint.js 另一部分注释,表示代码检查配置项
/*jshint quotmark:double */
/*global console:true */
/*exported console */

总之,本文所指「代码块」就是有特殊意义的注释。

什么是「代码块预处理」?

指在代码编译之前,将代码文件按代码块粒度做一次编码或解析。

举个栗子,原本无效的代码片段,经过编码后变成了有效代码。

预处理前:

/*<jdists>
console.log('Hello World!');
</jdists>*/

预处理后:

console.log('Hello World!');

市面上还有哪一些「代码块预处理工具」?

市面上有不少,这里只列两个比较典型的。

  • 已被普遍使用的 JSDoc,功能是将代码中的注释抽离成 API 文档。
/**
 * Represents a book.
 * @constructor
 * @param {string} title - The title of the book.
 * @param {string} author - The author of the book.
 */
function Book(title, author) {
   
}

  • JSDev 是由 JSON 之父 Douglas Crockford 编写。jdists 与 JSDev 的功能类似,但 jdists 功能要复杂很多。

C command line example:

   jsdev -comment "Devel Edition." <input >output test_expose enter:trace.enter exit:trace.exit unless:alert

JavaScript:

    output = JSDEV(input, [
        "test_expose",
        "enter:trace.enter",
        "exit:trace.exit",
        "unless:alert"
    ] , ["Devel Edition."]);

input:

    // This is a sample file.

    function Constructor(number) {
   
        /*enter 'Constructor'*/
        /*unless(typeof number !== 'number') 'number', "Type error"*/
        function private_method() {
   
            /*enter 'private_method'*/
            /*exit 'private_method'*/
        }
        /*test_expose
            this.private_method = private_method;
        */
        this.priv = function () {
   
            /*enter 'priv'*/
            private_method();
            /*exit 'priv'*/
        }
        /*exit "Constructor"*/
    }

output:

    // Devel Edition.
    // This is a sample file.

    function Constructor(number) {
   
        {trace.enter('Constructor');}
        if (typeof number !== 'number') {alert('number', "Type error");}
        function private_method() {
   
            {trace.enter('private_method');}
            {trace.exit('private_method');}
        }
        {
            this.private_method = private_method;
        }
        this.priv = function () {
   
            {trace.enter('priv');}
            private_method();
            {trace.exit('priv');}
        }
        {trace.exit("Constructor");}
    }

lightly minified:

    function Constructor(number) {
   
        function private_method() {
   
        }
        this.priv = function () {
   
            private_method();
        }
    }

预处理以「代码块」为粒度有什么优势?

  • 处理速度快,按需对代码块部分进行指定编码;
  • 控制力更强,可以控制每个字符的变化;
  • 不干扰编译器,编译器天然忽略注释。

现有「代码块预处理工具」存在什么问题?

  • 不容易学习和记忆。begin 还是 start,前缀还是后缀?
<!-- 乐居广告脚本 begin-->
/* jshint ignore:start */
/* TODO 待开发功能 */
  • 是否存在闭合不明显。什么时候生效,什么时候失效?
/*jshint unused:true, eqnull:true*/
/*test_expose
    this.private_method = private_method;
  */
  • 没有标准,不能跨语言。JSDev 和 JSDoc 不能用于其他主流语言,如 Python、Lua 等。

代码预处理的思考

问题也就是:怎么定义、怎么处理、什么情况下触发。

怎么定义「代码块」?

本人拟订了一个基于「XML 标签」+「多行注释」的代码块规范: CBML

CBML

优势:

  • 学习成本低,XML、多行注释都是大家熟知的东西;
  • 标签是否闭合很明显;
  • 支持多种主流编程语言。

怎么处理「代码块」?

处理的步骤无外乎就是:输入、编码、输出

processor

经过解析 CBML 的语法树,获取 tagattribute 两个关键信息。

如果 tag 值为 <jdists> 就开始按 jdists 的规则进行处理。

整个处理过程由四个关键属性决定:
1. import= 指定输入媒介
2. export= 指定输出媒介
3. encoding= 指定编码集合
4. trigger= 指定触发条件

举个例子

/*<jdists export="template.js" trigger="@version < '1.0.0'">
  var template = /*<jdists encoding="base64,quoted" import="main.html?template" />*/
/*</jdists>

这里有两个代码块,还是一个嵌套结构

  • 外层代码块属性 export="template.js" 指定内容导出到文件 template.js(目录相对于当
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 12
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值