
Research
Malicious npm Packages Impersonate Flashbots SDKs, Targeting Ethereum Wallet Credentials
Four npm packages disguised as cryptographic tools steal developer credentials and send them to attacker-controlled Telegram infrastructure.
标签: jdists 教程
通常软件发布时会将源文件做一次「预处理」再编译成可执行文件,才发布到市场。
一些 IDE 已在「编译」时集成了「预处理」功能。
jdists 是一款强大的代码块预处理工具。
通常就是注释或注释包裹的代码片段,用于表达各种各样的含义。
举个栗子
/* TODO 功能待开发 */
<!-- bower:css -->
<link rel="stylesheet" href="bower_components/css/bootstrap.css" />
<!-- endbower -->
/*!
* 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 quotmark:double */
/*global console:true */
/*exported console */
总之,本文所指「代码块」就是有特殊意义的注释。
指在代码编译之前,将代码文件按代码块粒度做一次编码或解析。
举个栗子,原本无效的代码片段,经过编码后变成了有效代码。
预处理前:
/*<jdists>
console.log('Hello World!');
</jdists>*/
预处理后:
console.log('Hello World!');
市面上有不少,这里只列两个比较典型的。
/**
* Represents a book.
* @constructor
* @param {string} title - The title of the book.
* @param {string} author - The author of the book.
*/
function Book(title, author) {
}
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;
*/
问题也就是:怎么定义、怎么处理、什么情况下触发。
本人拟订了一个基于「XML 标签」+「多行注释」的代码块规范: CBML
优势:
处理的步骤无外乎就是:输入、编码、输出
经过解析 CBML 的语法树,获取 tag
和 attribute
两个关键信息。
如果 tag
值为 <jdists>
就开始按 jdists 的规则进行处理。
整个处理过程由四个关键属性决定:
import=
指定输入媒介export=
指定输出媒介encoding=
指定编码集合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
(目录相对于当前代码块所在的文件)。trigger="@version < '1.0.0'"
指定命令行参数 version
小于 '1.0.0'
才触发。encoding="base64,quoted"
表示先给内容做一次 base64
编码再做一次 quoted
即,编码成字符串字面量。有两个触发条件:
tag
值为 <jdists>
或者是被配置为 jdists
标签trigger=
表达式判断为 true
由 tag 标识的代码区域
代码块主要有如下三种形式:
/*<jdists import="main.js" />*/
/*<jdists encoding="uglify">*/
function format(template, json) {
if (typeof template === 'function') { // 函数多行注释处理
template = String(template).replace(
/[^]*\/\*!?\s*|\s*\*\/[^]*/g, // 替换掉函数前后部分
''
);
}
return template.replace(/#\{(.*?)\}/g, function(all, key) {
return json && (key in json) ? json[key] : "";
});
}
/*</jdists>*/
/*<jdists>
console.log('version: %s', version);
<jdists>*/
<jdists>
| 自定义import=
指定输入媒介export=
指定输出媒介encoding=
指定编码集合trigger=
指定触发条件&content
默认为 "&"
file
文件
> 如:
> main.js
> index.html
#variant
变量
> 如:
> #name
> #data
[file]?block
readonly 代码块,默认 file
为当前文件
> 如:
> filename?tagName
> filename?tagName[attrName=attrValue]
> filename?tagName[attrName=attrValue][attrName2=attrValue2]
@argument
readonly 控制台参数
> 如:
> @output
> @version
:environment
readonly 环境变量
> 如:
> :HOME
> :USER
[...]
、{...}
readonly 字面量
> 如:
> [1, 2, 3, 4]
> {title: 'jdists'}
'string'
readonly 字符串
> 如:
> 'zswang'
触发器有两种表达式
--trigger
是否存在交集,存在则被触发当
$ jdists ... --trigger release
触发
<!--remove trigger="release"-->
<label>release</label>
<!--/remove-->
当
$ jdists ... --version 0.0.9
触发
<!--remove trigger="@version < '1.0.0'"-->
<label>1.0.0+</label>
<!--/remove-->
可以参考项目中 processor 目录,中自带编码器的写法
举个栗子
var ejs = require('ejs');
/**
* ejs 模板渲染
*
* @param {string} content 文本内容
* @param {Object} attrs 属性
* @param {string} attrs.data 数据项
* @param {Object} scope 作用域
* @param {Function} scope.execImport 导入数据
* @param {Function} scope.compile 二次编译 jdists 文本
*/
module.exports = function processor(content, attrs, scope) {
if (!content) {
return content;
}
var render = ejs.compile(content);
var data;
if (attrs.data) {
/*jslint evil: true */
data = new Function(
'return (' +
scope.execImport(attrs.data) +
');'
)();
}
else {
data = null;
}
return scope.compile(render(data));
};
详情参考:jdists Scope
通过块导入
<!--remove-->
<script>
/*<jdists encoding="base64" id="code">*/
console.log('hello world!');
/*</jdists>*/
</script>
<!--/remove-->
<!--jdists>
<script src="data:application/javascript;base64,/*<jdists import="?[id=code]" />*/"></script>
</jdists-->
通过变量导入
<!--remove-->
<script>
/*<jdists encoding="base64" export="#code">*/
console.log('hello world!');
/*</jdists>*/
</script>
<!--/remove-->
<!--jdists>
<script src="data:application/javascript;base64,/*<jdists import="#code" />*/"></script>
</jdists-->
jdists 依赖 node v0.10.0 以上的环境
$ npm install jdists [-g]
Usage:
jdists <input list> [options]
Options:
-r, --remove Remove block tag name list (default "remove,test")
-o, --output Output file (default STDOUT)
-v, --version Output jdists version
-t, --trigger Trigger name list (default "release")
-c, --config Path to config file (default ".jdistsrc")
var content = jdists.build(filename, {
remove: 'remove,debug',
trigger: 'release'
});
https://github.com/zswang/jdists/issues
$ git clone https://github.com/zswang/jdists.git
$ npm install
$ npm test
$ npm run dist
$ npm run cover
[lib] --- 发布后的代码目录
jdists.js --- jdists 业务代码
scope.js --- jdists 作用域
[processor] --- 预制编码器
[processor-extend] --- 未预制的编码器,可能会常用的
[src] --- 开发期代码
[test] --- 测试目录
[fixtures] --- 测试用例
test.js --- 测试调度文件
index.js --- jdists 声明
cli.js --- jdists 控制台
FAQs
Code block processing tools
The npm package jdists receives a total of 108 weekly downloads. As such, jdists popularity was classified as not popular.
We found that jdists demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Four npm packages disguised as cryptographic tools steal developer credentials and send them to attacker-controlled Telegram infrastructure.
Security News
Ruby maintainers from Bundler and rbenv teams are building rv to bring Python uv's speed and unified tooling approach to Ruby development.
Security News
Following last week’s supply chain attack, Nx published findings on the GitHub Actions exploit and moved npm publishing to Trusted Publishers.