diff --git a/README.md b/README.md
index 4e7b28c..923dc75 100644
--- a/README.md
+++ b/README.md
@@ -35,34 +35,41 @@ npm包不能保证最新代码,最新代码以仓库代码为准!
 
 ```console
  $ npx rs-reverse makecode -h
- rs-reverse makecode
+rs-reverse makecode
 
-生成动态代码
+接收ts.json文件生成immucfg、ts、ts-full文件,如果传入的是url则还会生成html、主代
+码、动态代码文件,还可通过-j命令接收多个$_ts.l__处理的文件url并生成该js文件及解
+密后的js文件。
+
+**`-j`参数需要注意,链接地址必须带上查询参数,不带的话返回的是未经过瑞数处理的文件,可以从浏览器控制台查看带参数的完整地址,如果待解密的js文件存在多个时,为了保证结果中变量名与瑞数解析的变量名一致,需要按浏览器的解析顺序依序传入(因为变量名存在复用逻辑)。**
 
 Options:
   -h             显示帮助信息                                          [boolean]
   -f, --file     含有nsd, cd值的json文件                                [string]
   -l, --level    日志打印等级,参考log4js,默认为info                   [string]
   -u, --url      瑞数返回204状态码的请求地址                            [string]
-  -v, --version  显示版本号                                            [boolean]
-
-Examples:
-  rs-reverse makecode -f example/codes/1-$_ts.json
-  rs-reverse makecode -u http://url/path
+  -a, --adapt    已经做了适配的网站名称,不传则为cnipa                  [string]
+  -j, --jsurls   $_ts.__l方法执行的js文件链接(必须带上查询参数),多个时需要按顺
+                 序传入,如:-j "https://host/chunk.js?4VGu1xaT=a728b2" -j
+                 "https://host/app.js?4VGu1xaT=a728b2"                   [array]
+  -v, --version  显示版本号
 ```
 
 调用示例:
 
 ```bash
- $ npx rs-reverse makecode -u https://wcjs.sbj.cnipa.gov.cn/sgtmi
+ $ npx rs-reverse makecode -u https://wcjs.sbj.cnipa.gov.cn/sgtmi -j 'https://wcjs.sbj.cnipa.gov.cn/js/chunk-vendors.66e24864.js?查询参数' -j 'https://wcjs.sbj.cnipa.gov.cn/js/app.9f7a91c9.js?查询参数'
 
-  url方式提取的ts:/path/to/output/makecode_input_ts.json
-  url方式提取的静态文本:/path/to/output/makecode_input_immucfg.json
-  url方式提取的javascript代码:/path/to/output/makecode_input_js.js
-  url方式提取的html代码:/path/to/output/makecode_input_html.html
-
-  程序生成的ts:/path/to/output/makecode_output_ts.json
-  程序生成的动态代码:/path/to/output/makecode_output_code.js
+  url方式提取的ts:output/makecode/ts.json
+  url方式提取的静态文本:output/makecode/immucfg.json
+  程序生成的ts:output/makecode/ts-full.json
+  url方式提取的html代码:output/makecode/sgtmi.html
+  url方式提取的javascript代码:output/makecode/cCdzB9ZjDFks.a728b22.js
+  cCdzB9ZjDFks.a728b22.js生成的动态代码:output/makecode/cCdzB9ZjDFks.a728b22-dynamic.js
+  url方式提取的javascript代码:output/makecode/chunk-vendors.66e24864.js
+  chunk-vendors.66e24864.js生成的解密代码:output/makecode/chunk-vendors.66e24864-decrypt.js
+  url方式提取的javascript代码:output/makecode/app.9f7a91c9.js
+  app.9f7a91c9.js生成的解密代码:output/makecode/app.9f7a91c9-decrypt.js
 
 ```
 
@@ -79,7 +86,7 @@ Examples:
  $ npx rs-reverse makecookie -h
 rs-reverse makecookie
 
-生成动态代码
+生成cookie值并打印
 
 Options:
   -h             显示帮助信息                                          [boolean]
@@ -88,10 +95,6 @@ Options:
   -u, --url      瑞数返回204状态码的请求地址                            [string]
   -a, --adapt    已经做了适配的网站名称,不传则为cnipa                  [string]
   -v, --version  显示版本号                                            [boolean]
-
-Examples:
-  rs-reverse makecookie -f example/codes/1-$_ts.json
-  rs-reverse makecookie -u http://url/path
 ```
 
 调用示例:
@@ -99,9 +102,6 @@ Examples:
 ```bash
  $ npx rs-reverse makecookie -u https://wcjs.sbj.cnipa.gov.cn/sgtmi
 
-  url方式提取的ts:/path/to/output/makecookie_url_ts_1704391389883.json
-  url方式提取的静态文本:/path/to/output/makecookie_url_immutext_1704391389883.json
-
   存在meta-content值:n5fQ9G1lGvUzfS_yMHx30yYAbp2_NDZI 解析结果:/sgtmi
 
   Cookie值: 0yk64LrpoFnc8Wi4Mmu_rijgRRoC2SHY1bQlR2_QZ805_CqRd1uOgGRnlEvHvXSoQuwkx_fwn4iQnPDFrQigm1b4GnD61Pf9vU5XKtJtAWIoWeG_22OLiccUwGjI0lQaJ_jaYIBFygNsPSPf_0GnJyT1umFrFgAkAoqh1s0G9IDE1uPEM3PV8M1J.wbKdSgMLg8T3bGD5w2sHHohKfnwsT7bMNbb8xbjSxsn8qb8AvY0
@@ -111,7 +111,7 @@ Examples:
 
 ### 2.3. makecode-high子命令
 
-执行子命令`makecode-high`生成cookie,解码两次请求返回的网站代码(功能涵盖makecode子命令),调用示例:
+执行子命令`makecode-high`生成网站代码,解码两次请求返回的网站代码(功能涵盖makecode子命令),调用示例:
 
 1. npx方式:`npx rs-reverse makecode-high -u url`
 2. 文件方式:`node main.js makecode-high -u url`
@@ -130,7 +130,6 @@ rs-reverse makecode-high
 
 Options:
   -h             显示帮助信息                                          [boolean]
-  -f
   -l, --level    日志打印等级,参考log4js,默认为info                   [string]
   -u, --url      瑞数返回204状态码的请求地址                 [string] [required]
   -a, --adapt    已经做了适配的网站名称,不传则为cnipa                  [string]
@@ -147,25 +146,25 @@ Examples:
 
 第1次请求:
 
-  url方式提取的ts:/path/to/output/makecode-high/first/ts.json
-  url方式提取的静态文本:/path/to/output/makecode-high/first/immucfg.json
-  程序生成的ts:/path/to/output/makecode-high/first/ts-full.json
-  url方式提取的javascript代码:/path/to/output/makecode-high/first/cCdzB9ZjDFks.a728b22.js
-  url方式提取的html代码:/path/to/output/makecode-high/first/sgtmi.html
-  cCdzB9ZjDFks.a728b22.js生成的动态代码:/path/to/output/makecode-high/first/cCdzB9ZjDFks.a728b22-dynamic.js
+  url方式提取的ts:output/makecode-high/first/ts.json
+  url方式提取的静态文本:output/makecode-high/first/immucfg.json
+  程序生成的ts:output/makecode-high/first/ts-full.json
+  url方式提取的javascript代码:output/makecode-high/first/cCdzB9ZjDFks.a728b22.js
+  url方式提取的html代码:output/makecode-high/first/sgtmi.html
+  cCdzB9ZjDFks.a728b22.js生成的动态代码:output/makecode-high/first/cCdzB9ZjDFks.a728b22-dynamic.js
 
 第2次请求:
 
-  url方式提取的ts:/path/to/output/makecode-high/second/ts.json
-  url方式提取的静态文本:/path/to/output/makecode-high/second/immucfg.json
-  程序生成的ts:/path/to/output/makecode-high/second/ts-full.json
-  url方式提取的javascript代码:/path/to/output/makecode-high/second/cCdzB9ZjDFks.a728b22.js
-  url方式提取的html代码:/path/to/output/makecode-high/second/sgtmi.html
-  cCdzB9ZjDFks.a728b22.js生成的动态代码:/path/to/output/makecode-high/second/cCdzB9ZjDFks.a728b22-dynamic.js
-  url方式提取的javascript代码:/path/to/output/makecode-high/second/chunk-vendors.66e24864.js
-  url方式提取的javascript代码:/path/to/output/makecode-high/second/app.9f7a91c9.js
-  chunk-vendors.66e24864.js生成的解密代码:/path/to/output/makecode-high/second/chunk-vendors.66e24864-decrypt.js
-  app.9f7a91c9.js生成的解密代码:/path/to/output/makecode-high/second/app.9f7a91c9-decrypt.js
+  url方式提取的ts:output/makecode-high/second/ts.json
+  url方式提取的静态文本:output/makecode-high/second/immucfg.json
+  程序生成的ts:output/makecode-high/second/ts-full.json
+  url方式提取的javascript代码:output/makecode-high/second/cCdzB9ZjDFks.a728b22.js
+  url方式提取的html代码:output/makecode-high/second/sgtmi.html
+  cCdzB9ZjDFks.a728b22.js生成的动态代码:output/makecode-high/second/cCdzB9ZjDFks.a728b22-dynamic.js
+  url方式提取的javascript代码:output/makecode-high/second/chunk-vendors.66e24864.js
+  url方式提取的javascript代码:output/makecode-high/second/app.9f7a91c9.js
+  chunk-vendors.66e24864.js生成的解密代码:output/makecode-high/second/chunk-vendors.66e24864-decrypt.js
+  app.9f7a91c9.js生成的解密代码:output/makecode-high/second/app.9f7a91c9-decrypt.js
 
 ```
 
diff --git a/main.js b/main.js
index adf507a..d12b986 100755
--- a/main.js
+++ b/main.js
@@ -14,6 +14,8 @@ const pkg = require(paths.package);
 const log4js = require('log4js');
 const adapt = require('@src/adapt');
 const gv = require('@src/handler/globalVarible');
+const _merge = require('lodash/merge');
+const _omit = require('lodash/omit');
 
 function debugLog(level) {
   if (level) {
@@ -67,11 +69,8 @@ const commandHandler = (command, argv) => {
   logger.trace(`传入的$_ts.cd: ${ts.cd}`);
   gv._setAttr('argv', argv);
   try {
-    if (argv.url) {
-      command(ts, adapt(argv.url, argv.adapt), argv.url);
-    } else {
-      command(ts);
-    }
+    const immucfg = argv.url ? adapt(argv.url, argv.adapt) : undefined;
+    command(ts, immucfg, _merge(argv.url || {}, argv.jsurls || {}));
   } catch (err) {
     logger.error(err.stack);
   }
@@ -84,16 +83,23 @@ module.exports = yargs
   .usage('使用: node $0 <commond> [options]')
   .command({
     command: 'makecode',
-    describe: '生成动态代码',
-    builder: commandBuilder,
+    describe: '接收ts.json文件生成immucfg、ts、ts-full文件,如果传入的是url则还会生成html、主代码、动态代码文件,还可通过-j命令接收多个$_ts.l__处理的文件url并生成该js文件及解密后的js文件',
+    builder: {
+      ...commandBuilder,
+      j: {
+        alias: 'jsurls',
+        describe: '$_ts.__l方法执行的js文件链接(必须带上查询参数),多个时需要按顺序传入,如:-j "https://host/chunk.js?4VGu1xaT=a728b2" -j "https://host/app.js?4VGu1xaT=a728b2"',
+        type: 'array',
+        coerce: getCode,
+      }
+    },
     handler: commandHandler.bind(null, makeCode),
   })
   .command({
     command: 'makecode-high',
     describe: '解码两次请求返回的网站代码(功能涵盖makecode子命令)',
     builder: {
-      ...commandBuilder,
-      f: undefined,
+      ..._omit(commandBuilder, ['f']),
       u: {
         ...commandBuilder.u,
         demandOption: true,
diff --git a/package.json b/package.json
index c879c31..075de4d 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "rs-reverse",
-  "version": "1.7.1",
+  "version": "1.7.2",
   "description": "瑞数算法逆向,website reverse engineering",
   "main": "main.js",
   "directories": {
@@ -36,7 +36,7 @@
     "registry": "https://registry.npmjs.org/"
   },
   "author": "pysunday",
-  "license": "ISC",
+  "license": "BSD 3-Clause",
   "dependencies": {
     "cheerio": "^1.0.0-rc.12",
     "fs-extra": "^11.2.0",
diff --git a/src/handler/AppCode.js b/src/handler/AppCode.js
index c955802..ac650d5 100644
--- a/src/handler/AppCode.js
+++ b/src/handler/AppCode.js
@@ -1,5 +1,7 @@
 const gv = require('@src/handler/globalVarible');
 
+let maxLen = 0; // 用于与瑞数代码逻辑一致,瑞数逻辑是当数组长度少于上一次生成的数组则复用上一次的数组
+
 module.exports = class {
   constructor(params, idx) {
     this.oper = 0;
@@ -38,15 +40,18 @@ module.exports = class {
   getKeys(len) {
     const keys = [];
     for(let i = 0; i <= len; i++) {
-      const j = Math.floor((this.random || Math.random()) * 4294967295) % len + 0;
+      const j = Math.floor((Math.random()) * 4294967295) % len + 0;
+      const temp = keys[i];
       keys[i] = keys[j] || `$_${j}`;
-      keys[j] = `$_${i}`;
+      keys[j] = temp || `$_${i}`;
     }
     return keys;
   }
 
-  decrypt() {
-    const keys = this.getKeys(this.getLength());
+  decrypt(isMerge = false) {
+    // isMerge:是否将变量数组合并到代码中
+    maxLen = Math.max(this.getLength(), maxLen);
+    const keys = this.getKeys(maxLen);
     const name = `$$_${this.idx}`;
     const num = this.getLength();
     const ret = new Array(num), res = [];
@@ -71,16 +76,14 @@ module.exports = class {
           ret[i] = val;
           break;
         case 4:
-          // ret[i] = `${name}[${next}]`;
-          ret[i] = `"${staticText[next]}"`;
+          ret[i] = isMerge ? `"${staticText[next]}"` : `${name}[${next}]`;
           break;
         case 5:
           ret[i] = this.params[2][next]
           break;
       }
     }
-    // return `window[${name}]=${JSON.stringify(staticText)};${ret.join('')}`;
-    return ret.join('');
+    return isMerge ? ret.join('') : `window.${name}=${JSON.stringify(staticText)};\n${ret.join('')}`;
   }
 
   run() {
@@ -91,4 +94,13 @@ module.exports = class {
     };
     return code;
   }
+
+  static getParams(code) {
+    // 去除外层的$_ts.l__方法
+    if (typeof code !== 'string' || code.indexOf('$_ts.l__') !== 0) {
+      throw new Error('解码网站渲染代码未发现$_ts.l__前缀,请检查!');
+    }
+    const $_ts = { l__: (...params) => params };
+    return eval(code);
+  }
 }
diff --git a/src/makeCode.js b/src/makeCode.js
index 73defae..b25af75 100644
--- a/src/makeCode.js
+++ b/src/makeCode.js
@@ -1,56 +1,73 @@
+const AppCode = require('./handler/AppCode');
 const Coder = require('./handler/Coder');
 const paths = require('@utils/paths');
 const fs = require('fs');
+const fse = require('fs-extra');
 const logger = require('@utils/logger');
+const { init } = require('@src/handler/parser/');
+
+function filenameAddDesc(name, desc) {
+  const arr = name.split('.');
+  if (arr.length < 2) throw new Error(`文件名不正确: ${name}`);
+  arr[arr.length - 2] += desc;
+  return arr.join('.');
+}
+
+function writeFile(ts, immucfg, { jscode, html, appcode = [] }, $_ts, code) {
+  const files = [
+    {
+      name: 'ts.json',
+      desc: immucfg ? 'url方式提取的ts:' : '程序接收的ts:',
+      text: JSON.stringify(ts),
+    },
+    immucfg ? {
+      name: 'immucfg.json',
+      desc: 'url方式提取的静态文本:',
+      text: JSON.stringify(immucfg),
+    } : null,
+    {
+      name: 'ts-full.json',
+      desc: '程序生成的ts:',
+      text: JSON.stringify($_ts),
+    },
+    html,
+    jscode,
+    {
+      name: jscode ? filenameAddDesc(jscode.name, '-dynamic') : 'dynamic.js',
+      desc: `${jscode?.name || '程序'}生成的动态代码:`,
+      text: '// 该行标记来源,非动态代码生成: ' + JSON.stringify(ts) + '\n\n' + code,
+    },
+    ...appcode.reduce((ans, it) => {
+      ans.push(it);
+      if (it.decryptCode) {
+        ans.push({
+          name: filenameAddDesc(it.name, '-decrypt'),
+          desc: `${it.name}生成的解密代码:`,
+          text: it.decryptCode,
+        });
+      }
+      return ans;
+    }, []),
+  ].filter(Boolean).map(it => ({ ...it, filepath: paths.outputResolve('makecode', it.name) }))
+  if (!fs.existsSync(paths.outputResolve('makecode'))) fse.ensureDirSync(paths.outputResolve('makecode'));
+  files.forEach(({ filepath, text, code }) => filepath && fs.writeFileSync(filepath, text || code));
+  return files;
+}
 
 module.exports = function (ts, immucfg, mate = {}) {
   const startTime = new Date().getTime();
+  if (fs.existsSync(paths.outputResolve('makecode'))) {
+    fse.moveSync(paths.outputResolve('makecode'), paths.outputResolve('makecode-old'), { overwrite: true });
+  }
   const coder = new Coder(ts, immucfg);
   const { code, $_ts } = coder.run();
-  const files = [
-    immucfg ? {
-      name: 'makecode_input_ts',
-      desc: 'url方式提取的ts:',
-      text: JSON.stringify(ts),
-      extend: 'json',
-    } : null,
-    immucfg ? {
-      name: 'makecode_input_immucfg',
-      desc: 'url方式提取的静态文本:',
-      text: JSON.stringify(immucfg),
-      extend: 'json',
-    } : null,
-    mate.jscode ? {
-      name: 'makecode_input_js',
-      desc: 'url方式提取的javascript代码:',
-      text: mate.jscode.code,
-      extend: 'js',
-    } : null,
-    mate.html ? {
-      name: 'makecode_input_html',
-      desc: 'url方式提取的html代码:',
-      text: mate.html.code,
-      extend: 'html',
-      newLine: true,
-    } : null,
-    {
-      name: 'makecode_output_ts',
-      desc: '程序生成的ts:',
-      text: JSON.stringify($_ts),
-      extend: 'json',
-    },
-    {
-      name: 'makecode_output_code',
-      desc: '程序生成的动态代码:',
-      text: '// 该行标记来源,非动态代码生成: ' + JSON.stringify(ts) + '\n\n' + code,
-      extend: 'js',
-    },
-  ].filter(Boolean).map(it => ({ ...it, filepath: `${paths.outputResolve(it.name)}.${it.extend}` }))
-  if (!fs.existsSync(paths.outputPath)) fs.mkdirSync(paths.outputPath);
-  files.forEach(({ filepath, text }) => fs.writeFileSync(filepath, text))
+  init($_ts);
+  mate.appcode?.forEach((appcode, idx) => {
+    appcode.decryptCode = new AppCode(AppCode.getParams(appcode.code)).run();
+  });
+  const files = writeFile(ts, immucfg, mate, $_ts, code);
   logger.info([
-    `生成动态代码成功!用时:${new Date().getTime() - startTime}ms\n`,
-    ...files.reduce((ans, it, idx) => ([...ans, `${it.desc}${it.filepath}${idx === files.length - 1 || it.newLine ? '\n' : ''}`]), []),
+    `代码还原成功!用时:${new Date().getTime() - startTime}ms\n`,
+    ...files.reduce((ans, it, idx) => ([...ans, typeof it === 'string' ? it : `${it.desc}${paths.relative(it.filepath)}${idx === files.length - 1 || it.newLine ? '\n' : ''}`]), []),
   ].join('\n  '));
 }
-
diff --git a/src/makeCodeHigh.js b/src/makeCodeHigh.js
index 05c7f9e..9333314 100644
--- a/src/makeCodeHigh.js
+++ b/src/makeCodeHigh.js
@@ -18,13 +18,6 @@ function parseR2mka(text) {
   return unescape(text.substr(start, end));
 }
 
-function mkdirsSync(dirPath) {
-  if (!fs.existsSync(dirPath)) {
-    mkdirsSync(path.dirname(dirPath));
-    fs.mkdirSync(dirPath);
-  }
-}
-
 function filenameAddDesc(name, desc) {
   const arr = name.split('.');
   if (arr.length < 2) throw new Error(`文件名不正确: ${name}`);
@@ -63,16 +56,10 @@ function writeFile(step, ts, immucfg, { jscode, html, appcode = [] }, $_ts, code
       text: it.decryptCode,
     }))
   ].filter(Boolean).map(it => ({ ...it, filepath: paths.outputResolve('makecode-high', step, it.name) }))
-  if (!fs.existsSync(paths.outputResolve('makecode-high', step))) mkdirsSync(paths.outputResolve('makecode-high', step));
+  if (!fs.existsSync(paths.outputResolve('makecode-high', step))) fse.ensureDirSync(paths.outputResolve('makecode-high', step));
   return files;
 }
 
-function decryptAppCode(appcode, idx) {
-  const $_ts = { l__: (...params) => params };
-  const codeParams = eval(appcode.code);
-  appcode.decryptCode = new AppCode(codeParams, idx + 1).run();
-}
-
 function firstStep(ts, immucfg, mate) {
   gv._setAttr('_ts', ts);
   const coder = new Coder(ts, immucfg);
@@ -88,7 +75,9 @@ function secondStep(ts, immucfg, mate) {
   gv._setAttr('_ts', ts);
   const coder = new Coder(ts, immucfg);
   const { code, $_ts } = coder.run();
-  mate.appcode.map(decryptAppCode);
+  mate.appcode.forEach((appcode, idx) => {
+    appcode.decryptCode = new AppCode(AppCode.getParams(appcode.code)).run();
+  });
   return writeFile('second', ts, immucfg, mate, $_ts, code);
 }
 
@@ -104,7 +93,7 @@ module.exports = async function (ts, immucfg, mate) {
   files.forEach(({ filepath, text, code }) => filepath && fs.writeFileSync(filepath, text || code));
   logger.info([
     `代码还原成功!用时:${new Date().getTime() - startTime}ms\n`,
-    ...files.reduce((ans, it, idx) => ([...ans, typeof it === 'string' ? it : `${it.desc}${it.filepath}${idx === files.length - 1 || it.newLine ? '\n' : ''}`]), []),
+    ...files.reduce((ans, it, idx) => ([...ans, typeof it === 'string' ? it : `${it.desc}${paths.relative(it.filepath)}${idx === files.length - 1 || it.newLine ? '\n' : ''}`]), []),
   ].join('\n  '));
 }
 
diff --git a/src/makeCookie.js b/src/makeCookie.js
index a81108b..fe30015 100644
--- a/src/makeCookie.js
+++ b/src/makeCookie.js
@@ -34,7 +34,7 @@ function writefile(ts, immucfg) {
 
 module.exports = function (ts, immucfg) {
   gv._setAttr('_ts', ts);
-  if (immucfg) writefile(ts, immucfg);
+  // if (immucfg) writefile(ts, immucfg);
   const startTime = new Date().getTime();
   const coder = new Coder(ts, immucfg);
   const { code, $_ts } = coder.run();
diff --git a/utils/getCode.js b/utils/getCode.js
index bebb95e..405ab2e 100644
--- a/utils/getCode.js
+++ b/utils/getCode.js
@@ -26,7 +26,7 @@ function nameHandle(name, extend) {
   return name.split('.').pop() === extend ? name : `${name}.${extend}`;
 }
 
-module.exports = async function getCode(url, cookieStr) {
+async function getCodeByHtml(url, cookieStr) {
   if (cookieStr) {
     cookieJar.setCookie(request.cookie(cookieStr), url);
   }
@@ -53,8 +53,14 @@ module.exports = async function getCode(url, cookieStr) {
     appcode: [],
     url,
   }
-  for(let src of remotes) {
-    const jsurl = urlresolve(url, src);
+  await getCodeByJs(remotes.map(it => urlresolve(url, it)), ret);
+  if (ret.jscode) return ret;
+  throw new Error('js外链中没有瑞数的代码文件');
+}
+
+async function getCodeByJs(urls, ret = { appcode: [] }) {
+  for(let url of urls) if (!isValidUrl(url)) throw new Error(`输入链接不正确:${url}`);
+  for(let jsurl of urls) {
     const name = jsurl.split('?')[0].split('/').pop();
     const jscode = await request(addRequestHead(jsurl));
     const data = {
@@ -69,6 +75,14 @@ module.exports = async function getCode(url, cookieStr) {
       ret.jscode = data;
     }
   }
-  if (ret.jscode) return ret;
-  throw new Error('js外链中没有瑞数的代码文件');
+  return ret;
+}
+
+module.exports = function getCode(url, ...params) {
+  if (typeof url === 'string') {
+    return getCodeByHtml(url, ...params);
+  }
+  if (Array.isArray(url)) {
+    return getCodeByJs(url);
+  }
 }
diff --git a/utils/paths.js b/utils/paths.js
index 811df84..f5f69cf 100644
--- a/utils/paths.js
+++ b/utils/paths.js
@@ -23,4 +23,5 @@ module.exports = {
   outputResolve: (...p) => path.resolve('output', ...p),
   examplePath: resolveApp('example'),
   exampleResolve: (...p) => resolveApp('example', ...p),
+  relative: (p) => path.relative(path.resolve(), p),
 };