index.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. // 声明所有全局内容
  2. var sa_mcontent = {
  3. // 例如:定义res, 你可以在md文档中使用 import(res),来导入这一段话
  4. res: '``` js\n\t{\n\t\t"code": 200, // 成功时=200, 失败时=500 msg=失败原因\n\t\t"msg": "ok",\n\t\t"data": {}\n\t} \n```'
  5. };
  6. // 声明插件
  7. var sa_plugins = function(hook) {
  8. // 解析之前执行
  9. hook.beforeEach(function(content) {
  10. content = refMd_p2table(content); // 参数转表格
  11. content = refMd_import2content(content); // 加载import
  12. content = refMd_api2trim(content); // api去除空格
  13. content = refMd_var(content); // 更换变量
  14. return content;
  15. });
  16. // 解析之后执行
  17. hook.afterEach(function(html) {
  18. // 添加页脚
  19. var footer = [
  20. '<br/><br/><br/><br/><br/><br/><br/><hr/>',
  21. '<footer>',
  22. '&emsp;<span>本接口文档使用 <a href="https://github.com/click33/sa-doc" target="_blank">sa-doc</a> 编写</span>',
  23. // '<span>Proudly published with <a href="https://github.com/docsifyjs/docsify" target="_blank">docsify</a>.</span>',
  24. '</footer>'
  25. ].join('');
  26. return html + footer;
  27. });
  28. function f5_test_btn() {
  29. // console.log(123);
  30. $('.anchor').each(function(index, el) {
  31. try{
  32. // 获取父元素
  33. var parTag = $(this).parent('h3');
  34. if(parTag == null) {
  35. return;
  36. }
  37. var tagName = parTag.prop("tagName");
  38. if(tagName != 'H3') {
  39. return;
  40. }
  41. // 地址、参数等信息
  42. var cc_id = sa.randomString(16); // id号码
  43. window.apiInfoMap = window.apiInfoMap || {}; // 存储当前页面所有api信息
  44. window.apiInfoMap[cc_id] = { // 此项的所有信息
  45. // api_title: parTag.find('a span').text(), // 接口标题
  46. ajaxUrl: '', // 接口地址
  47. ajaxType: 'GET', // 接口请求方式
  48. headerList: [], // 请求头参数
  49. bodyList: [], // 请求体参数
  50. };
  51. var apiInfo = window.apiInfoMap[cc_id];
  52. var nextTagArr = $(parTag).nextAll();
  53. for (var i = 0; i < nextTagArr.length; i++) {
  54. var tag = $(nextTagArr.get(i));
  55. // 如果已经到了H3了,则可以结束了
  56. if(tag.prop("tagName") == 'H3') {
  57. break;
  58. }
  59. // 如果是参数
  60. if(tag.prop("tagName") == 'TABLE') {
  61. var trArr = $(tag).find('tbody tr');
  62. for (var j = 0; j < trArr.length; j++) {
  63. var tdArr = $(trArr.get(j)).find('td');
  64. apiInfo.bodyList.push({name: tdArr.get(0).innerHTML, value: '', tips: tdArr.get(3).innerHTML}); // , value: tdArr.get(3)
  65. }
  66. }
  67. // 如果是参数
  68. // if(tag.prop("tagName") == 'DIV' && tag.prop('class') == 'body-p-list') {
  69. // var text = tag.text();
  70. // var trArr = JSON.parse(text);
  71. // console.log(trArr.length);
  72. // for (var j = 0; j < trArr.length; j++) {
  73. // var tdArr = trArr[j];
  74. // apiInfo.bodyList.push({name: tdArr[0], value: '', tips: tdArr[3]}); // , value: tdArr[2]
  75. // }
  76. // }
  77. // 如果是地址
  78. if(tag.prop("tagName") == 'UL') {
  79. // 如果能搜索到 data-lang="api"
  80. var tg = $(tag).find('[class=lang-api]');
  81. if(tg.length > 0) {
  82. var url_i = tg.get(0).innerHTML;
  83. if(url_i.indexOf('http') != 0) {
  84. url_i = sa_doc_cfg.server_url + url_i;;
  85. }
  86. apiInfo.ajaxUrl = url_i;
  87. }
  88. }
  89. }
  90. // console.log(nextAll.length);
  91. // console.log(tagName);
  92. // 后面添加一个按钮
  93. // parTag.after('<button>测试接口</button>');
  94. // console.log(parTag.find('a span').text());
  95. var button = '<button class="test-api-btn" type="button" '+
  96. ' cc-id="' + cc_id + '" ' +
  97. ' api-title="' + parTag.find('a span').text() + '" ' +
  98. ' onclick="test_api(this)">接口测试</button>';
  99. parTag.append(button);
  100. }catch(e){
  101. console.err(e);
  102. }
  103. })
  104. }
  105. // 渲染完全完成之后
  106. hook.doneEach(function() {
  107. f5_test_btn();
  108. });
  109. };
  110. // 点击测试接口的按钮
  111. function test_api(event) {
  112. // console.log(event.classList);
  113. // 获取参数
  114. // 获取title
  115. var j_index = document.title.indexOf('-');
  116. var title = document.title;
  117. if(j_index > -1) {
  118. title = title.substr(0, j_index);
  119. title = event.getAttribute('api-title') + ' &emsp;&emsp;----by&emsp; ' + title;
  120. }
  121. // 获取地址、参数等信息
  122. var id = event.getAttribute('cc-id');
  123. var cc = window.apiInfoMap[id];
  124. console.log(cc);
  125. // var cc = {
  126. // ajaxType: 'GET',
  127. // ajaxUrl: 'dsada',
  128. // headerList: [],
  129. // bodyList: []
  130. // }
  131. sessionStorage.setItem('sa-doc-cc-' + id, JSON.stringify(cc));
  132. sa.showIframe3(title, './sa-lib/api-test/index.html?id=' + id, '1000px', '90%');
  133. }
  134. // 移除数组中所有空白字符串
  135. function arrayTrimSpace(array) {
  136. for (var i = 0; i < array.length; i++) {
  137. if (array[i] == "" || array[i] == " " || array[i] == null || typeof(array[i]) == "undefined") {
  138. array.splice(i, 1);
  139. i = i - 1;
  140. }
  141. }
  142. return array;
  143. }
  144. // 获取一行表格
  145. // 参数名字,类型,默认值,说明
  146. function getTrMd(name, type, default_value, remrak) {
  147. var str = '\n|' + name + '|' + type + '|' + default_value + '|' + remrak + '|';
  148. return str;
  149. }
  150. // 加工md,将其中的```p 转换为table格式
  151. function refMd_p2table(content) {
  152. // 1、取出全文中所有的 ```d
  153. var reg = /```\s*p[\s\S]*?```/igm; // [\s\S]*=任意字符n次,?=非贪婪模式
  154. var pArr = content.match(reg)|| [];; // 返回所有匹配项数组
  155. // 遍历并转换
  156. pArr.forEach(function(p) {
  157. // 声明表头
  158. var table = '\n' +
  159. '| 参数名称| 类型| 默认值|说明|\n' +
  160. '| :--------| :--------| :--------|:--------|';
  161. // 将这个p内容按换行符切割
  162. var canStr = p.replace(/```\s*p/, '').replace('```', '').trim(); // 去除首行尾行
  163. var canArr = canStr.split('\n') || []; // 按行切割
  164. // var bodyPList = []; // 二维数组记录一下参数集合
  165. // 开始逐行转换为tr
  166. canArr.forEach(function(canStr) {
  167. // 去除空格
  168. canStr = canStr.trim();
  169. // 声明四大变量的值
  170. let name = ''; // 参数名子
  171. let type = ''; // 数据类型
  172. let default_value = ''; // 默认值
  173. let remrak = ''; // 参数说明
  174. // 如果带有数据类型
  175. if(canStr.indexOf('{') > -1 && canStr.indexOf('}') > -1) {
  176. canStr = canStr.replace('{', ''); // 去除掉前{
  177. let sjArr = canStr.split('}'); // 按照}分割
  178. type = sjArr[0].trim();
  179. canStr = sjArr[1].trim();
  180. }
  181. // 切割成数组
  182. var canArray = canStr.split(/[\s\t\n]/) || [];
  183. // canArray = arrayTrimSpace(canArray); // 去除空格元素
  184. // 如果开发者写的不规范,使其超过2个元素,则强制改为2个元素
  185. if(canArray.length == 0) {
  186. return;
  187. }
  188. if(canArray.length == 1) {
  189. canArray.push('');
  190. }
  191. // =========== 开始判断 5种情况 ==================
  192. let one = canArray[0];
  193. let two = canArray[1];
  194. // 情况1 id=1 xxxx
  195. if(one.indexOf('=') > -1 && one.indexOf('=') < one.length - 1) {
  196. name = one.split('=')[0];
  197. default_value = one.split('=')[1];
  198. canArray.splice(0, 1);
  199. }
  200. // 情况2 id= 1 xxxx
  201. else if(one.indexOf('=') == one.length - 1) {
  202. name = one.split('=')[0];
  203. default_value = two;
  204. canArray.splice(0, 2);
  205. }
  206. // 情况3 id =1 xxxx
  207. else if(one.indexOf('=') == -1 && two.indexOf('=') == 0 && two.length > 1) {
  208. name = one;
  209. default_value = two.split('=')[1];
  210. canArray.splice(0, 2);
  211. }
  212. // 情况4 id = 1 xxxx
  213. else if(one.indexOf('=') == -1 && two == '=') {
  214. name = one;
  215. default_value = canArray[2] || '';
  216. canArray.splice(0, 3);
  217. }
  218. // 情况5 id 1 xxxx 或其它
  219. // else if(one.indexOf('=') == -1 && two.indexOf('=') != 0) {
  220. else {
  221. name = one;
  222. canArray.splice(0, 1);
  223. }
  224. // 剩下的元素,都拼接remrak
  225. remrak = canArray.join('');
  226. // 添加到表格
  227. table += getTrMd(name, type, default_value, remrak);
  228. // bodyPList.push([name, type, default_value, remrak]);
  229. })
  230. // console.log(p);
  231. // 将原始p内容替换成为table内容
  232. table += '\n';
  233. // table += '\n<div class="body-p-list" style="display: none;">' + JSON.stringify(bodyPList) + '</div>\n'; // 增加上参数信息
  234. content = content.replace(p, table);
  235. });
  236. return content;
  237. }
  238. // 加工md,将其中的@import 转换为真实内容
  239. function refMd_import2content(content) {
  240. // 1、取出全文中所有的 ```d
  241. var reg = /@import\([\s\S]*?\)/igm; // [\s\S]*=任意字符n次,?=非贪婪模式
  242. var importArr = content.match(reg)|| []; // 返回所有匹配项数组
  243. // 遍历并转换
  244. importArr.forEach(function(import_item) {
  245. // 过滤空格
  246. // console.log(import_item);
  247. var item = import_item.replace(' ', '').replace('@import(', '').replace(')', '');
  248. // 开始替换
  249. content = content.replace(import_item, sa_mcontent[item] || '');
  250. });
  251. return content;
  252. }
  253. // 加工md,将其中的```api 去除空格
  254. function refMd_api2trim(content) {
  255. // 1、取出全文中所有的 ```d
  256. var reg = /```\s*api[\s\S]*?```/igm; // [\s\S]*=任意字符n次,?=非贪婪模式
  257. var pArr = content.match(reg)|| [];; // 返回所有匹配项数组
  258. // 遍历并转换
  259. pArr.forEach(function(p) {
  260. // 将这个p内容按换行符切割
  261. var canStr = p.replace(/```\s*api/, '').replace('```', '').trim(); // 去除首行尾行
  262. var canArr = canStr.split('\n') || []; // 按行切割
  263. var str = '';
  264. // 遍历并转换
  265. canArr.forEach(function(p) {
  266. str += p;
  267. });
  268. str = '``` api\n' + str + '```\n';
  269. // console.log(str);
  270. // 加上按钮
  271. // str = '<button>测试接口</button>\n' + str;
  272. // 将原始p内容替换成为后来内容
  273. content = content.replace(p, str);
  274. })
  275. return content;
  276. }
  277. // 加工md,将其中的变量
  278. function refMd_var(content) {
  279. content = content.replace('${sa_doc_cfg.server_url}', window.sa_doc_cfg.server_url);
  280. return content;
  281. }
  282. // 打印信息
  283. console.log('欢迎使用sa-doc(一个基于markdown的接口文档编写工具),当前版本:v1.3.0,更新于:2020-07-2,GitHub地址:https://github.com/click33/sa-doc');
  284. console.log('如在使用中发现任何bug或者疑问,请加入QQ群交流:782974737,点击加入:https://jq.qq.com/?_wv=1027&k=5DHN5Ib');