作者 lihongjuan

班级打卡二开

要显示太多修改。

为保证性能只显示 12 of 12+ 个文件。

  1 +//app.js
  2 +App({
  3 + onLaunch: function() {
  4 + if (wx.canIUse('getUpdateManager')) {
  5 + const updateManager = wx.getUpdateManager()
  6 + updateManager.onCheckForUpdate(function (res) {
  7 + console.log('onCheckForUpdate====', res)
  8 + // 请求完新版本信息的回调
  9 + if (res.hasUpdate) {
  10 + console.log('res.hasUpdate====')
  11 + updateManager.onUpdateReady(function () {
  12 + wx.showModal({
  13 + title: '更新提示',
  14 + content: '新版本已经准备好,是否重启应用?',
  15 + success: function (res) {
  16 + console.log('success====', res)
  17 + // res: {errMsg: "showModal: ok", cancel: false, confirm: true}
  18 + if (res.confirm) {
  19 + // 新的版本已经下载好,调用 applyUpdate 应用新版本并重启
  20 + updateManager.applyUpdate()
  21 + }
  22 + }
  23 + })
  24 + })
  25 + updateManager.onUpdateFailed(function () {
  26 + // 新的版本下载失败
  27 + wx.showModal({
  28 + title: '已经有新版本了哟~',
  29 + content: '新版本已经上线啦~,请您删除当前小程序,重新搜索打开哟~'
  30 + })
  31 + })
  32 + }
  33 + })
  34 + }
  35 + // 展示本地存储能力
  36 + var logs = wx.getStorageSync('logs') || []
  37 + logs.unshift(Date.now())
  38 + wx.setStorageSync('logs', logs)
  39 + // 登录
  40 + wx.login({
  41 + success: res => {
  42 + // 发送 res.code 到后台换取 openId, sessionKey, unionId
  43 + }
  44 + })
  45 + // 获取用户信息
  46 + wx.getSetting({
  47 + success: res => {
  48 + if (res.authSetting['scope.userInfo']) {
  49 + // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
  50 + wx.getUserInfo({
  51 + success: res => {
  52 + // 可以将 res 发送给后台解码出 unionId
  53 + this.globalData.userInfo = res.userInfo
  54 + // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
  55 + // 所以此处加入 callback 以防止这种情况
  56 + if (this.userInfoReadyCallback) {
  57 + this.userInfoReadyCallback(res)
  58 + }
  59 + }
  60 + })
  61 + }
  62 + }
  63 + })
  64 + },
  65 + onShow: function() {
  66 +
  67 + },
  68 + // uploadimg(data) {
  69 + // var that = this,
  70 + // i = data.i ? data.i : 0,
  71 + // success = data.success ? data.success : 0,
  72 + // fail = data.fail ? data.fail : 0;
  73 + // wx.uploadFile({
  74 + // url: data.url,
  75 + // filePath: data.path[i],
  76 + // name: 'file',
  77 + // formData: null,
  78 + // success: (resp) => {
  79 + // success++;
  80 + // //这里可能有BUG,失败也会执行这里
  81 + // },
  82 + // fail: (res) => {
  83 + // fail++;
  84 + // console.log('fail:' + i + "fail:" + fail);
  85 + // },
  86 + // complete: () => {
  87 + // i++;
  88 + // if (i == data.path.length) { //当图片传完时,停止调用
  89 + // console.log('成功:' + success + " 失败:" + fail);
  90 + // } else { //若图片还没有传完,则继续调用函数
  91 + // console.log(i);
  92 + // data.i = i;
  93 + // data.success = success;
  94 + // data.fail = fail;
  95 + // that.uploadimg(data);
  96 + // }
  97 + // }
  98 + // });
  99 + // },
  100 + globalData: {
  101 + userInfo: null,
  102 + },
  103 + post: function(url, data, headerParams) {
  104 + // wx.showNavigationBarLoading()
  105 + // wx.showLoading({
  106 + // title: '加载中',
  107 + // })
  108 + var promise = new Promise((resolve, reject) => {
  109 + let that = this;
  110 + let postData = data;
  111 + let baseUrl = 'https://banji.w.broing.cn';
  112 + // let baseUrl = 'http://banji2.t.brotop.cn';
  113 + //网络请求
  114 + let header = {
  115 + 'content-type': 'application/x-www-form-urlencoded',
  116 + 'token': wx.getStorageSync('token') || '',
  117 + }
  118 + // console.log(baseUrl/ + url)
  119 + header = Object.assign(header, headerParams)
  120 + wx.request({
  121 + url: baseUrl + url,
  122 + data: postData,
  123 + method: 'POST',
  124 + header: header,
  125 + success: function(res) { //返回取得的数据
  126 + if (res.statusCode == '200') {
  127 + resolve(res);
  128 + } else {
  129 + // wx.showModal({
  130 + // title: '提示',
  131 + // content: res.data.msg,
  132 + // showCancel: false,
  133 + // })
  134 + reject(res.data)
  135 + }
  136 + // wx.hideLoading()
  137 + // wx.hideNavigationBarLoading()
  138 + },
  139 + fail: function(e) {
  140 + console.log(e)
  141 + reject('网络出错');
  142 + // wx.hideLoading()
  143 + // wx.hideNavigationBarLoading()
  144 + }
  145 + })
  146 + });
  147 +
  148 + return promise;
  149 + },
  150 + quitTest(){
  151 + wx.showModal({
  152 + title:'提示',
  153 + content:'确认退出当前体验账户?',
  154 + success: function(res){
  155 + if(res.confirm){
  156 + wx.removeStorageSync('token');
  157 + wx.removeStorageSync('ident');
  158 + wx.removeStorageSync('testCount');
  159 + wx.reLaunch({
  160 + url: '/pages/choose/choose',
  161 + })
  162 + }
  163 + }
  164 +
  165 + })
  166 +
  167 +
  168 + },
  169 + gets: function (url, data, headerParams) {
  170 + // wx.showNavigationBarLoading()
  171 + // wx.showLoading({
  172 + // title: '加载中',
  173 + // })
  174 + var promise = new Promise((resolve, reject) => {
  175 + let that = this;
  176 + let postData = data;
  177 + let baseUrl = 'https://banji.w.broing.cn';
  178 + // let baseUrl = 'http://banji2.t.brotop.cn';
  179 + //网络请求
  180 + let header = {
  181 + 'content-type': 'application/x-www-form-urlencoded',
  182 + 'token': wx.getStorageSync('token') || '',
  183 + }
  184 + // console.log(baseUrl/ + url)
  185 + header = Object.assign(header, headerParams)
  186 + wx.request({
  187 + url: baseUrl + url,
  188 + data: postData,
  189 + method: 'GET',
  190 + header: header,
  191 + success: function (res) { //返回取得的数据
  192 + if (res.statusCode == '200') {
  193 + resolve(res);
  194 + } else {
  195 +
  196 + reject(res.data)
  197 + }
  198 + },
  199 + fail: function (e) {
  200 + console.log(e)
  201 + reject('网络出错');
  202 + }
  203 + })
  204 + });
  205 + return promise;
  206 + },
  207 + //第一种底部
  208 + editTabBar: function() {
  209 + //使用getCurrentPages可以获取当前加载中所有的页面对象的一个数组,数组最后一个就是当前页面。
  210 +
  211 + var curPageArr = getCurrentPages(); //获取加载的页面
  212 + var curPage = curPageArr[curPageArr.length - 1]; //获取当前页面的对象
  213 + var pagePath = curPage.route; //当前页面url
  214 + if (pagePath.indexOf('/') != 0) {
  215 + pagePath = '/' + pagePath;
  216 + }
  217 +
  218 + var tabBar = this.globalData.tabBar;
  219 + for (var i = 0; i < tabBar.list.length; i++) {
  220 + tabBar.list[i].active = false;
  221 + if (tabBar.list[i].pagePath == pagePath) {
  222 + tabBar.list[i].active = true; //根据页面地址设置当前页面状态
  223 + }
  224 + }
  225 + curPage.setData({
  226 + tabBar: tabBar
  227 + });
  228 + }, //第二种底部,原理同上
  229 + editTabBar1: function() {
  230 + var curPageArr = getCurrentPages();
  231 + var curPage = curPageArr[curPageArr.length - 1];
  232 + var pagePath = curPage.route;
  233 + if (pagePath.indexOf('/') != 0) {
  234 + pagePath = '/' + pagePath;
  235 + }
  236 + var tabBar = this.globalData.tabBar1;
  237 + for (var i = 0; i < tabBar.list.length; i++) {
  238 + tabBar.list[i].active = false;
  239 + if (tabBar.list[i].pagePath == pagePath) {
  240 + tabBar.list[i].active = true;
  241 + }
  242 + }
  243 + curPage.setData({
  244 + tabBar: tabBar
  245 + });
  246 + },
  247 + globalData: {
  248 + imgUrl: "https://banji.w.broing.cn",
  249 + cdnUrl: "https://banjiqiniu.broing.cn",
  250 + //第一种底部导航栏显示
  251 + tabBar: {
  252 + "color": "#9E9E9E",
  253 + "selectedColor": "#f00",
  254 + "backgroundColor": "#fff",
  255 + "borderStyle": "#ccc",
  256 + "list": [{
  257 + "pagePath": "/pages/index/index",
  258 + "text": "布置作业",
  259 + "iconPath": "/image/2.png",
  260 + "selectedIconPath": "/image/52.png",
  261 + "clas": "menu-item",
  262 + "selectedColor": "#000000",
  263 + active: true
  264 + },
  265 + {
  266 + "pagePath": "/pages/homework/homework",
  267 + "text": "收作业",
  268 + "iconPath": "/image/3.png",
  269 + "selectedIconPath": "/image/39.png",
  270 + "selectedColor": "#000000",
  271 + "clas": "menu-item",
  272 + active: false
  273 + },
  274 + {
  275 + "pagePath": "/pages/my/my",
  276 + "text": "我的",
  277 + "iconPath": "/image/1.png",
  278 + "selectedIconPath": "/image/84.png",
  279 + "selectedColor": "#000000",
  280 + "clas": "menu-item",
  281 + active: false
  282 + }
  283 + ],
  284 + "position": "bottom"
  285 + },
  286 + //第二种底部导航栏显示
  287 + tabBar1: {
  288 + "color": "#9E9E9E",
  289 + "selectedColor": "#f00",
  290 + "backgroundColor": "#fff",
  291 + "borderStyle": "#ccc",
  292 + "list": [{
  293 + "pagePath": "/pages/parentsDo/parentsDo",
  294 + "text": "写作业",
  295 + "iconPath": "/image/2.png",
  296 + "selectedIconPath": "/image/52.png",
  297 + "clas": "menu-item",
  298 + "selectedColor": "#000000",
  299 + active: true
  300 + },
  301 + {
  302 + "pagePath": "/pages/parentsList/parentsList",
  303 + "text": "小红花",
  304 + "iconPath": "/image/51.png",
  305 + "selectedIconPath": "/image/72.png",
  306 + "clas": "menu-item",
  307 + "selectedColor": "#000000",
  308 + active: false
  309 + },
  310 + {
  311 + "pagePath": "/pages/parentsMy/parentsMy",
  312 + "text": "我的",
  313 + "iconPath": "/image/1.png",
  314 + "selectedIconPath": "/image/84.png",
  315 + "selectedColor": "#000000",
  316 + "clas": "menu-item",
  317 + active: false
  318 + }
  319 + ],
  320 + "position": "bottom"
  321 + },
  322 + }
  323 +})
  1 +{
  2 + "pages": [
  3 + "pages/index/index",
  4 + "pages/myjiangzhuang/myjianghzuang",
  5 + "pages/dakajianzhuanh/dakajianzhuanh",
  6 + "pages/zuotyeliebiao/zuotyeliebiao",
  7 + "pages/myxunzhang/myxunzhang",
  8 + "pages/fafangjiangli/fafangjiangli",
  9 +
  10 + "pages/zuoye/zuoye",
  11 + "pages/flowerlist/flowerlist",
  12 + "pages/new_class/new_class",
  13 + "pages/new_class2/new_class2",
  14 + "pages/logs/logs",
  15 + "pages/choose/choose",
  16 + "pages/my/my",
  17 + "pages/detail/detail",
  18 + "pages/homework/homework",
  19 +
  20 + "pages/members/members",
  21 + "pages/personal/personal",
  22 + "pages/classDetail/classDetail",
  23 + "pages/kinship/kinship",
  24 + "pages/list/list",
  25 + "pages/classSet/classSet",
  26 + "pages/problem/problem",
  27 + "pages/parentsList/parentsList",
  28 + "pages/service/service",
  29 + "pages/joinClass/joinClass",
  30 + "pages/parentsDo/parentsDo",
  31 + "pages/video/video",
  32 + "pages/parentsMy/parentsMy",
  33 + "pages/submit/submit",
  34 + "pages/workRecord/workRecord",
  35 + "pages/parentsDetail/parentsDetail",
  36 + "pages/home/home",
  37 + "pages/mark/mark",
  38 + "pages/searchClass/searchClass",
  39 + "pages/commentList/commentList",
  40 + "pages/scoreDetail/scoreDetail"
  41 +
  42 + ],
  43 + "window": {
  44 + "backgroundTextStyle": "light",
  45 + "navigationBarBackgroundColor": "#fff",
  46 + "navigationBarTitleText": "WeChat"
  47 + },
  48 + "sitemapLocation": "sitemap.json"
  49 +}
  1 +/**app.wxss**/
  2 +page {
  3 + background-color: #f6f6f6;
  4 +}
  5 +
  6 +image{
  7 + width: 100%;
  8 + height: 100%;
  9 + display: block;
  10 +}
  11 +.menu-item{
  12 + width: 100%;
  13 + float: left;
  14 + text-align: center;
  15 + padding-top: 8px;
  16 +}
  17 +.menu-item1{
  18 + width: 24%;
  19 + float: left;
  20 + text-align: center;
  21 + padding-top: 8px;
  22 +}
  23 +.img{
  24 + width: 40rpx;
  25 + height: 40rpx;
  26 + display: block;
  27 + margin:auto;
  28 +}
  29 +.switch{
  30 + width: 33.3%;
  31 + float: left;
  32 + background-color: none;
  33 +}
  34 +.clear{
  35 + clear: both;
  36 +}
  37 +.tab-bar{
  38 + position: fixed;
  39 + width: 100%;
  40 + padding: 0rpx 2%;
  41 + z-index: 100;
  42 + background-color: white;
  43 +}
  44 +
  45 +.button{
  46 + margin: 130px;
  47 +}
  48 +.footer_bottos{
  49 + position: fixed;
  50 + bottom: 0;
  51 + left: 0;
  52 + width: 100%;
  53 + height: 92rpx;
  54 + display: flex;
  55 + justify-content: space-around;
  56 + align-items: center;
  57 + border-top:solid 1px #ccc;
  58 + background-color: white;
  59 +}
  60 +.footer_liImg{
  61 + width: 42rpx;
  62 +}
  63 +.footer_li{
  64 + width: 33.3%;
  65 + display: flex;
  66 + flex-direction: column;
  67 + align-items: center;
  68 +}
  69 +.footer_txt{
  70 + font-size:22rpx;
  71 + margin-top: 4rpx;
  72 + color:rgba(190,190,190,1);
  73 +}
  74 +@font-face {
  75 + font-family: 'iconfont'; /* project id 562638 */
  76 + src: url('//at.alicdn.com/t/font_562638_joq4abt1a345z5mi.eot');
  77 + src: url('//at.alicdn.com/t/font_562638_joq4abt1a345z5mi.eot?#iefix') format('embedded-opentype'),
  78 + url('//at.alicdn.com/t/font_562638_joq4abt1a345z5mi.woff') format('woff'),
  79 + url('//at.alicdn.com/t/font_562638_joq4abt1a345z5mi.ttf') format('truetype'),
  80 + url('//at.alicdn.com/t/font_562638_joq4abt1a345z5mi.svg#iconfont') format('svg');
  81 +}
  82 +.iconfont {
  83 + font-family: "iconfont" !important;
  84 + font-size: 32rpx;
  85 + font-style: normal;
  86 + -webkit-font-smoothing: antialiased;
  87 + -moz-osx-font-smoothing: grayscale;
  88 +}
  89 +
  90 +
  91 +.icon-pinglun3:before {
  92 + content: "\e63a";
  93 +}
  94 +
  95 +.icon-dizhi:before {
  96 + content: "\e61f";
  97 +}
  98 +
  99 +.icon-weixin1:before {
  100 + content: "\e695";
  101 +}
  102 +
  103 +.icon-weixin2:before {
  104 + content: "\e62a";
  105 +}
  106 +
  107 +.icon-dianzan:before {
  108 + content: "\e673";
  109 +}
  110 +
  111 +.icon-tianjiajiahaowubiankuang:before {
  112 + content: "\e81a";
  113 +}
  114 +
  115 +.icon-mojiezuo:before {
  116 + content: "\e611";
  117 +}
  118 +
  119 +.icon-shuangzizuo:before {
  120 + content: "\e615";
  121 +}
  122 +
  123 +.icon-shuipingzuo:before {
  124 + content: "\e616";
  125 +}
  126 +
  127 +.icon-bofang2:before {
  128 + content: "\e639";
  129 +}
  130 +
  131 +.icon-pinglun1:before {
  132 + content: "\e618";
  133 +}
  134 +
  135 +.icon-icon25:before {
  136 + content: "\e631";
  137 +}
  138 +
  139 +.icon-nan:before {
  140 + content: "\e661";
  141 +}
  142 +
  143 +.icon-baiyangzuo:before {
  144 + content: "\e637";
  145 +}
  146 +
  147 +.icon-juxiezuo:before {
  148 + content: "\e63d";
  149 +}
  150 +
  151 +.icon-shizizuo:before {
  152 + content: "\e645";
  153 +}
  154 +
  155 +.icon-shuangyuzuo:before {
  156 + content: "\e646";
  157 +}
  158 +
  159 +.icon-xin:before {
  160 + content: "\e6b3";
  161 +}
  162 +
  163 +.icon-bangzhujinru:before {
  164 + content: "\e64e";
  165 +}
  166 +
  167 +.icon-fujin:before {
  168 + content: "\e620";
  169 +}
  170 +
  171 +.icon-nv:before {
  172 + content: "\e606";
  173 +}
  174 +
  175 +.icon-zhangdan:before {
  176 + content: "\e662";
  177 +}
  178 +
  179 +.icon-shouyejiedan:before {
  180 + content: "\e634";
  181 +}
  182 +
  183 +.icon-fabubiaoshu:before {
  184 + content: "\e613";
  185 +}
  186 +
  187 +.icon-fasong:before {
  188 + content: "\e614";
  189 +}
  190 +
  191 +.icon-mingpian2:before {
  192 + content: "\e623";
  193 +}
  194 +
  195 +.icon-xuanzhong:before {
  196 + content: "\e701";
  197 +}
  198 +
  199 +.icon-bofang:before {
  200 + content: "\e62e";
  201 +}
  202 +
  203 +.icon-guize:before {
  204 + content: "\e61d";
  205 +}
  206 +
  207 +.icon-wode:before {
  208 + content: "\e636";
  209 +}
  210 +
  211 +.icon-canyuqingkuang:before {
  212 + content: "\e707";
  213 +}
  214 +
  215 +.icon-xuqiu:before {
  216 + content: "\e641";
  217 +}
  218 +
  219 +.icon-choose:before {
  220 + content: "\e63b";
  221 +}
  222 +
  223 +.icon-shengyin:before {
  224 + content: "\e663";
  225 +}
  226 +
  227 +.icon-fenxiang:before {
  228 + content: "\e65c";
  229 +}
  230 +
  231 +.icon-baocun:before {
  232 + content: "\e612";
  233 +}
  234 +
  235 +.icon-huatong:before {
  236 + content: "\e67e";
  237 +}
  238 +
  239 +.icon-bofang1:before {
  240 + content: "\e632";
  241 +}
  242 +
  243 +.icon-xihuan1:before {
  244 + content: "\e630";
  245 +}
  246 +
  247 +.icon-guanzhu1:before {
  248 + content: "\e619";
  249 +}
  250 +
  251 +.icon-dianhua:before {
  252 + content: "\e627";
  253 +}
  254 +
  255 +.icon-pinglun2:before {
  256 + content: "\e642";
  257 +}
  258 +
  259 +.icon-shaixuan:before {
  260 + content: "\e64a";
  261 +}
  262 +
  263 +.icon-wenjianjia:before {
  264 + content: "\e63c";
  265 +}
  266 +
  267 +.icon-weizhi:before {
  268 + content: "\e68c";
  269 +}
  270 +
  271 +.icon-liwu:before {
  272 + content: "\e6c7";
  273 +}
  274 +
  275 +.icon-zhiye:before {
  276 + content: "\e628";
  277 +}
  278 +
  279 +.icon-shipin:before {
  280 + content: "\e64f";
  281 +}
  282 +
  283 +.icon-guanzhu:before {
  284 + content: "\e607";
  285 +}
  286 +
  287 +.icon-sousuo:before {
  288 + content: "\e60f";
  289 +}
  290 +
  291 +.icon-paotui2:before {
  292 + content: "\e621";
  293 +}
  294 +
  295 +.icon-zhaopian:before {
  296 + content: "\e625";
  297 +}
  298 +
  299 +.icon-shuangren:before {
  300 + content: "\e633";
  301 +}
  302 +
  303 +.icon-genggai:before {
  304 + content: "\e648";
  305 +}
  306 +
  307 +.icon-fabu:before {
  308 + content: "\e60d";
  309 +}
  310 +
  311 +.icon-shouji:before {
  312 + content: "\e626";
  313 +}
  314 +
  315 +.icon-touxiangxian:before {
  316 + content: "\e8d5";
  317 +}
  318 +
  319 +.icon-xihuan:before {
  320 + content: "\e6f1";
  321 +}
  322 +
  323 +.icon-shizhong:before {
  324 + content: "\e676";
  325 +}
  326 +
  327 +.icon-yaoqing:before {
  328 + content: "\e61e";
  329 +}
  330 +
  331 +.icon-shengri:before {
  332 + content: "\e731";
  333 +}
  334 +
  335 +.icon-hs_s_Single_h-danzi:before {
  336 + content: "\e73b";
  337 +}
  338 +
  339 +.icon-pinglun:before {
  340 + content: "\e62f";
  341 +}
  342 +
  343 +.icon-add:before {
  344 + content: "\e604";
  345 +}
  346 +
  347 +.icon-collection:before {
  348 + content: "\e60b";
  349 +}
  350 +
  351 +.icon-collection-b:before {
  352 + content: "\e60e";
  353 +}
  354 +
  355 +.icon-camera2:before {
  356 + content: "\e61a";
  357 +}
  358 +
  359 +.icon-gifs:before {
  360 + content: "\e624";
  361 +}
  362 +
  363 +.icon-icon--:before {
  364 + content: "\e788";
  365 +}
  366 +
  367 +.icon-icon-1:before {
  368 + content: "\e617";
  369 +}
  370 +
  371 +.icon-icon-test4:before {
  372 + content: "\e63e";
  373 +}
  374 +
  375 +.icon-icon-:before {
  376 + content: "\e6dd";
  377 +}
  378 +
  379 +.icon-xiaoxi:before {
  380 + content: "\e62b";
  381 +}
  382 +
  383 +.icon-yixiangkehu:before {
  384 + content: "\e629";
  385 +}
  386 +
  387 +.icon-quxiao1:before {
  388 + content: "\e609";
  389 +}
  390 +
  391 +.icon-quxiaoguanzhux:before {
  392 + content: "\e61b";
  393 +}
  394 +
  395 +.icon-wode1:before {
  396 + content: "\e602";
  397 +}
  398 +
  399 +.icon-collect:before {
  400 + content: "\e63f";
  401 +}
  402 +
  403 +.icon-icon_add:before {
  404 + content: "\e640";
  405 +}
  406 +
  407 +.icon-menu_icon_normal:before {
  408 + content: "\e643";
  409 +}
  410 +
  411 +.icon-menu_icon_select:before {
  412 + content: "\e649";
  413 +}
  414 +
  415 +.icon-menu_icon_normal1:before {
  416 + content: "\e64b";
  417 +}
  418 +
  419 +.icon-menu_icon_select1:before {
  420 + content: "\e64c";
  421 +}
  422 +
  423 +.icon-arrow:before {
  424 + content: "\e64d";
  425 +}
  426 +
  427 +.icon-search:before {
  428 + content: "\e650";
  429 +}
  430 +
  431 +.icon-hdxq_icon:before {
  432 + content: "\e651";
  433 +}
  434 +
  435 +.icon-page_right:before {
  436 + content: "\e652";
  437 +}
  438 +
  439 +.icon-my_iconsmall:before {
  440 + content: "\e653";
  441 +}
  442 +
  443 +.icon-xingzhuang:before {
  444 + content: "\e654";
  445 +}
  446 +
  447 +.icon-xingzhuang1:before {
  448 + content: "\e655";
  449 +}
  450 +
  451 +.icon-icon-test:before {
  452 + content: "\e656";
  453 +}
  454 +
  455 +.icon-icon-test1:before {
  456 + content: "\e658";
  457 +}
  458 +
  459 +.icon-icon-test2:before {
  460 + content: "\e659";
  461 +}
  462 +
  463 +.icon-icon-test3:before {
  464 + content: "\e65a";
  465 +}
  466 +
  467 +.icon-icon-test5:before {
  468 + content: "\e65b";
  469 +}
  470 +
  471 +.icon-kaobei:before {
  472 + content: "\e65d";
  473 +}
  474 +
  475 +.icon-jiangbei:before {
  476 + content: "\e65e";
  477 +}
  478 +
  479 +.icon-bofang11:before {
  480 + content: "\e65f";
  481 +}
  482 +
  483 +.icon-tingzhi:before {
  484 + content: "\e660";
  485 +}
  486 +
  487 +.icon-zanting:before {
  488 + content: "\e664";
  489 +}
  490 +
  491 +.icon-zanting1:before {
  492 + content: "\e665";
  493 +}
  494 +
  495 +.icon-nv {
  496 + color: RGBA(255, 71, 204, 1);
  497 +}
  498 +
  499 +.icon-nan {
  500 + color: RGBA(57, 143, 202, 1);
  501 +}
  502 +
  503 +.gogngao_cion{
  504 + width: 90rpx;
  505 + height: 90rpx;
  506 + flex-flow:column;
  507 + border-radius: 60rpx;
  508 + font-size: 24rpx;
  509 + color: #FFF;
  510 + background: #4DA9FF;
  511 + display: flex;
  512 + align-items: center;
  513 + justify-content: center;
  514 + position: fixed;
  515 + right: 12rpx;
  516 + bottom: 240rpx;
  517 +}
  518 +.gogngao_cion image{
  519 + width: 50rpx;
  520 + height: 50rpx;
  521 +}
  522 +.note_box{
  523 + background: #F6F6F6;
  524 + display: flex;
  525 + justify-content: flex-end;
  526 + color: #5592f7;
  527 + font-size: 24rpx;
  528 + padding-bottom: 10rpx;
  529 + padding-right: 20rpx;
  530 +}
  531 +.note_box image{
  532 + width: 30rpx;
  533 + height: 30rpx;
  534 +}
  535 +.quitTestCount{
  536 + height: 30px;
  537 + padding:0 20px;
  538 + padding-right: 10px;
  539 + position: fixed;
  540 + left: 25px;
  541 + transform: translateX(-50%);
  542 + top: 55px;
  543 + font-size: 24rpx;
  544 + background: #4DA0FF;
  545 + color: #FFF;
  546 + line-height: 30px;
  547 +border-radius: 30px;
  548 + text-align: center;
  549 + overflow:hidden;
  550 + z-index: 99;
  551 +}
  552 +
  553 +.flex {
  554 + display: flex;
  555 +}
  556 +
  557 +.flexone {
  558 + display: flex;
  559 + align-items: center;
  560 +}
  561 +
  562 +.flextwo {
  563 + display: flex;
  564 + align-items: center;
  565 + justify-content: space-between;
  566 +}
  567 +
  568 +.flexthree {
  569 + display: flex;
  570 + align-items: center;
  571 + justify-content: center;
  572 +}
  573 +
  574 +.flexfour {
  575 + display: flex;
  576 + flex-direction: column;
  577 + align-items: center;
  578 + justify-content: center;
  579 +}
  580 +.flexfive {
  581 + display: flex;
  582 + flex-direction: column;
  583 + align-items: center;
  584 + justify-content: space-around;
  585 +}
  586 +.flexsix{
  587 + display: flex;
  588 + align-items: center;
  589 + justify-content: flex-end;
  590 +}
  1 +// components/pickerYMDHM/pickerYMDHM.js
  2 +Component({
  3 + /**
  4 + * 组件的属性列表
  5 + */
  6 + properties: {
  7 + date: { // 属性名
  8 + type: null, // 类型(必填),目前接受的类型包括:String, Number, Boolean, Object, Array, null(表示任意类型)
  9 + value: null // 属性初始值(可选),如果未指定则会根据类型选择一个
  10 + },
  11 + startDate: {
  12 + type: null, // 类型(必填),目前接受的类型包括:String, Number, Boolean, Object, Array, null(表示任意类型)
  13 + value: null // 属性初始值(可选),如果未指定则会根据类型选择一个
  14 + },
  15 + endDate: {
  16 + type: null, // 类型(必填),目前接受的类型包括:String, Number, Boolean, Object, Array, null(表示任意类型)
  17 + value: null // 属性初始值(可选),如果未指定则会根据类型选择一个
  18 + },
  19 + disabled: {
  20 + type: null, // 类型(必填),目前接受的类型包括:String, Number, Boolean, Object, Array, null(表示任意类型)
  21 + value: false // 属性初始值(可选),如果未指定则会根据类型选择一个
  22 + },
  23 + placeholder: {
  24 + type: null, // 类型(必填),目前接受的类型包括:String, Number, Boolean, Object, Array, null(表示任意类型)
  25 + value: null // 属性初始值(可选),如果未指定则会根据类型选择一个
  26 + }
  27 + },
  28 +
  29 + /**
  30 + * 组件的初始数据
  31 + */
  32 + data: {
  33 + pickerArray: [],//日期控件数据list
  34 + pickerIndex: [],//日期控件选择的index
  35 + chooseIndex: [],//日期控件确认选择的index
  36 + chooseArray: [],//日期控件确认选择后的list
  37 + dateString: '',//页面显示日期
  38 + // lis_RightInput:'lis_RightInput'
  39 + },
  40 + /**
  41 + * 组件的方法列表
  42 + */
  43 + methods: {
  44 + _onInit() {
  45 + let date = new Date();
  46 + if (this.data.date != null) {
  47 + let str = this.data.date;
  48 + str = str.replace(/-/g, "/");
  49 + date = new Date(str);
  50 + }
  51 + let pickerArray = this.data.pickerArray;
  52 + // console.log(date.getFullYear());
  53 + //默认选择3年内
  54 + let year = [];
  55 + let startDate = date.getFullYear() - 1;
  56 + let endDate = date.getFullYear() + 1;
  57 + if (this.data.startDate != null) {
  58 + //如果存在开始时间,则默认设置结束时间为2099
  59 + startDate = this.data.startDate;
  60 + endDate = 2099;
  61 + }
  62 + if (this.data.endDate != null && this.data.startDate == null) {
  63 + //如果存在结束时间,不存在开始时间 则默认设置开始时间为1900
  64 + endDate = this.data.endDate;
  65 + startDate = 1900;
  66 + }
  67 + if (this.data.endDate != null && this.data.startDate != null) {
  68 + endDate = this.data.endDate;
  69 + }
  70 + if (startDate > date.getFullYear() || endDate < date.getFullYear()) {
  71 + this.setData({
  72 + dateString: "默认日期不在时间范围内"
  73 + })
  74 + return;
  75 + }
  76 + for (let i = startDate; i <= endDate; i++) {
  77 + year.push({ id: i, name: i + "年" });
  78 + }
  79 + // console.log(year);
  80 + let month = [];
  81 + for (let i = 1; i <= 12; i++) {
  82 + month.push({ id: i, name: i + "月" });
  83 + }
  84 + // console.log(month);
  85 + let dayNum = this._getNumOfDays(date.getFullYear(), date.getMonth() + 1);
  86 + let day = [];
  87 + for (let i = 1; i <= dayNum; i++) {
  88 + day.push({ id: i, name: i + "日" });
  89 + }
  90 + // console.log(day);
  91 + let time = [];
  92 + for (let i = 0; i <= 23; i++) {
  93 + if (i < 10) {
  94 + time.push({ id: i, name: "0" + i + "时" });
  95 + } else {
  96 + time.push({ id: i, name: i + "时" });
  97 + }
  98 + }
  99 + // console.log(time);
  100 + let division = [];
  101 + for (let i = 0; i <= 59; i++) {
  102 + if (i < 10) {
  103 + division.push({ id: i, name: "0" + i + "分" });
  104 + } else {
  105 + division.push({ id: i, name: i + "分" });
  106 + }
  107 + }
  108 + // console.log(division);
  109 + pickerArray[0] = year;
  110 + pickerArray[1] = month;
  111 + pickerArray[2] = day;
  112 + pickerArray[3] = time;
  113 + pickerArray[4] = division;
  114 + let mdate = {
  115 + date: date,
  116 + year: date.getFullYear() + '',
  117 + month: date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1 + '',
  118 + day: date.getDate() < 10 ? '0' + date.getDate() : date.getDate() + '',
  119 + time: date.getHours() < 10 ? '0' + date.getHours() : date.getHours() + '',
  120 + division: date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes() + ''
  121 + }
  122 + mdate.dateString = mdate.year + '-' + mdate.month + '-' + mdate.day + ' ' + mdate.time + ':' + mdate.division;
  123 + this.setData({
  124 + pickerArray,
  125 + pickerIndex: [date.getFullYear() - startDate, date.getMonth(), date.getDate() - 1, date.getHours(), date.getMinutes()],
  126 + chooseIndex: [date.getFullYear() - startDate, date.getMonth(), date.getDate() - 1, date.getHours(), date.getMinutes()],
  127 + chooseArray: pickerArray,
  128 + dateString: this.data.placeholder != null ? this.data.placeholder : mdate.dateString
  129 + })
  130 + // console.log(date);
  131 + //设置placeholder属性后 初始化不返回日期
  132 + if (this.data.placeholder == null) {
  133 + this.triggerEvent('onPickerChange', mdate);
  134 + }
  135 + // console.log(this.data.pickerArray);
  136 + // console.log(this._getNumOfDays(2018, 10));
  137 + },
  138 + /**
  139 + *
  140 + * 获取本月天数
  141 + * @param {number} year
  142 + * @param {number} month
  143 + * @param {number} [day=0] 0为本月0最后一天的
  144 + * @returns number 1-31
  145 + */
  146 + _getNumOfDays(year, month, day = 0) {
  147 + return new Date(year, month, day).getDate()
  148 + },
  149 + pickerChange: function (e) {
  150 + // console.log('picker发送选择改变,携带值为', e.detail.value)
  151 + let indexArr = e.detail.value;
  152 + // console.log(this.data.pickerArray[0][indexArr[0]].id + "\n" + this.data.pickerArray[1][indexArr[1]].id + "\n" + this.data.pickerArray[2][indexArr[2]].id);
  153 + const year = this.data.pickerArray[0][indexArr[0]].id;
  154 + const month = this.data.pickerArray[1][indexArr[1]].id;
  155 + const day = this.data.pickerArray[2][indexArr[2]].id;
  156 + const time = this.data.pickerArray[3][indexArr[3]].id;
  157 + const division = this.data.pickerArray[4][indexArr[4]].id;
  158 + let date = {
  159 + date: new Date(year + '-' + month + '-' + day + ' ' + time + ':' + division),
  160 + year: year + '',
  161 + month: month < 10 ? '0' + month : month + '',
  162 + day: day < 10 ? '0' + day : day + '',
  163 + time: time < 10 ? '0' + time : time + '',
  164 + division: division < 10 ? '0' + division : division + ''
  165 + }
  166 + date.dateString = date.year + '-' + date.month + '-' + date.day + ' ' + date.time + ':' + date.division;
  167 + // console.log(date);
  168 + this.setData({
  169 + chooseIndex: e.detail.value,
  170 + chooseArray: this.data.pickerArray,
  171 + dateString: date.dateString
  172 + })
  173 + this.triggerEvent('onPickerChange', date);
  174 + },
  175 + pickerColumnChange: function (e) {
  176 + // console.log('修改的列为', e.detail.column, ',值为', e.detail.value);
  177 + var data = {
  178 + pickerArray: this.data.pickerArray,
  179 + pickerIndex: this.data.pickerIndex
  180 + };
  181 + data.pickerIndex[e.detail.column] = e.detail.value;
  182 + if (e.detail.column == 1) {
  183 + let dayNum = this._getNumOfDays(data.pickerArray[0][data.pickerIndex[0]].id, e.detail.value + 1);
  184 + let day = [];
  185 + for (let i = 1; i <= dayNum; i++) {
  186 + day.push({ id: i, name: i + "日" });
  187 + }
  188 + if (dayNum < data.pickerIndex[2] + 1) {
  189 + data.pickerIndex[2] = dayNum - 1;
  190 + }
  191 + data.pickerArray[2] = day;
  192 + }
  193 + this.setData(data);
  194 + },
  195 + pickerCancel: function (e) {
  196 + // console.log("取消");
  197 + this.setData({
  198 + pickerIndex: this.data.chooseIndex,
  199 + pickerArray: this.data.chooseArray
  200 + })
  201 + },
  202 + },
  203 + // 以下是旧式的定义方式,可以保持对 <2.2.3 版本基础库的兼容
  204 + attached() {
  205 + // 在组件实例进入页面节点树时执行
  206 + // 在组件实例进入页面节点树时执行
  207 + // this._onInit();
  208 + },
  209 + ready() {
  210 + console.log('进入ready外层节点=', this.data.date);
  211 + this._onInit();
  212 + },
  213 + // 以下为新方法 >=2.2.3
  214 + lifetimes: {
  215 + attached() {
  216 + // 在组件实例进入页面节点树时执行
  217 + // this._onInit();
  218 + },
  219 + detached() {
  220 + // 在组件实例被从页面节点树移除时执行
  221 + },
  222 + ready() {
  223 + console.log('进入ready节点=', this.data.date);
  224 + this._onInit();
  225 + }
  226 + }
  227 +})
  1 + {
  2 + "component": true,
  3 + "usingComponents": {}
  4 + }
  1 +<!--components/pickerYMDHM/pickerYMDHM.wxml-->
  2 +
  3 + <picker disabled="{{disabled}}" mode="multiSelector" bindchange="pickerChange" bindcolumnchange="pickerColumnChange" bindcancel ="pickerCancel" value="{{pickerIndex}}" range="{{pickerArray}}" range-key="{{'name'}}">
  4 + <view class='pickerTime'>
  5 + <view class="lis_RightInput">{{dateString}}</view>
  6 + <view class='lis_RightImg'>
  7 + <image src='/image/4.png'></image>
  8 + </view>
  9 + </view>
  10 +
  11 + </picker>
  1 +
  2 +.lis_RightInput {
  3 + width: 340rpx;
  4 + text-align: right;
  5 + font-size:28rpx;
  6 + color: black;
  7 + height: 44rpx;
  8 +}
  9 +.pickerTime{
  10 + display: flex;
  11 + align-items: center
  12 +}
  13 +.lis_RightImg {
  14 + width: 44rpx;
  15 + height: 44rpx;
  16 + display: inline-block;
  17 + margin-left: 28rpx;
  18 + vertical-align: middle;
  19 +}
  1 +/**
  2 + * html2Json 改造来自: https://github.com/Jxck/html2json
  3 + *
  4 + *
  5 + * author: Di (微信小程序开发工程师)
  6 + * organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
  7 + * 垂直微信小程序开发交流社区
  8 + *
  9 + * github地址: https://github.com/icindy/wxParse
  10 + *
  11 + * for: 微信小程序富文本解析
  12 + * detail : http://weappdev.com/t/wxparse-alpha0-1-html-markdown/184
  13 + */
  14 +
  15 +var __placeImgeUrlHttps = "https";
  16 +var __emojisReg = '';
  17 +var __emojisBaseSrc = '';
  18 +var __emojis = {};
  19 +var wxDiscode = require('./wxDiscode.js');
  20 +var HTMLParser = require('./htmlparser.js');
  21 +// Empty Elements - HTML 5
  22 +var empty = makeMap("area,base,basefont,br,col,frame,hr,img,input,link,meta,param,embed,command,keygen,source,track,wbr");
  23 +// Block Elements - HTML 5
  24 +var block = makeMap("br,a,code,address,article,applet,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,iframe,ins,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video");
  25 +
  26 +// Inline Elements - HTML 5
  27 +var inline = makeMap("abbr,acronym,applet,b,basefont,bdo,big,button,cite,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var");
  28 +
  29 +// Elements that you can, intentionally, leave open
  30 +// (and which close themselves)
  31 +var closeSelf = makeMap("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr");
  32 +
  33 +// Attributes that have their values filled in disabled="disabled"
  34 +var fillAttrs = makeMap("checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected");
  35 +
  36 +// Special Elements (can contain anything)
  37 +var special = makeMap("wxxxcode-style,script,style,view,scroll-view,block");
  38 +function makeMap(str) {
  39 + var obj = {}, items = str.split(",");
  40 + for (var i = 0; i < items.length; i++)
  41 + obj[items[i]] = true;
  42 + return obj;
  43 +}
  44 +
  45 +function q(v) {
  46 + return '"' + v + '"';
  47 +}
  48 +
  49 +function removeDOCTYPE(html) {
  50 + return html
  51 + .replace(/<\?xml.*\?>\n/, '')
  52 + .replace(/<.*!doctype.*\>\n/, '')
  53 + .replace(/<.*!DOCTYPE.*\>\n/, '');
  54 +}
  55 +
  56 +function trimHtml(html) {
  57 + return html
  58 + .replace(/\r?\n+/g, '')
  59 + .replace(/<!--.*?-->/ig, '')
  60 + .replace(/\/\*.*?\*\//ig, '')
  61 + .replace(/[ ]+</ig, '<')
  62 +}
  63 +
  64 +
  65 +function html2json(html, bindName) {
  66 + //处理字符串
  67 + html = removeDOCTYPE(html);
  68 + html = trimHtml(html);
  69 + html = wxDiscode.strDiscode(html);
  70 + //生成node节点
  71 + var bufArray = [];
  72 + var results = {
  73 + node: bindName,
  74 + nodes: [],
  75 + images:[],
  76 + imageUrls:[]
  77 + };
  78 + var index = 0;
  79 + HTMLParser(html, {
  80 + start: function (tag, attrs, unary) {
  81 + //debug(tag, attrs, unary);
  82 + // node for this element
  83 + var node = {
  84 + node: 'element',
  85 + tag: tag,
  86 + };
  87 +
  88 + if (bufArray.length === 0) {
  89 + node.index = index.toString()
  90 + index += 1
  91 + } else {
  92 + var parent = bufArray[0];
  93 + if (parent.nodes === undefined) {
  94 + parent.nodes = [];
  95 + }
  96 + node.index = parent.index + '.' + parent.nodes.length
  97 + }
  98 +
  99 + if (block[tag]) {
  100 + node.tagType = "block";
  101 + } else if (inline[tag]) {
  102 + node.tagType = "inline";
  103 + } else if (closeSelf[tag]) {
  104 + node.tagType = "closeSelf";
  105 + }
  106 +
  107 + if (attrs.length !== 0) {
  108 + node.attr = attrs.reduce(function (pre, attr) {
  109 + var name = attr.name;
  110 + var value = attr.value;
  111 + if (name == 'class') {
  112 + // console.dir(value);
  113 + // value = value.join("")
  114 + node.classStr = value;
  115 + }
  116 + // has multi attibutes
  117 + // make it array of attribute
  118 + if (name == 'style') {
  119 + // console.dir(value);
  120 + // value = value.join("")
  121 + node.styleStr = value;
  122 + }
  123 + if (value.match(/ /)) {
  124 + value = value.split(' ');
  125 + }
  126 +
  127 +
  128 + // if attr already exists
  129 + // merge it
  130 + if (pre[name]) {
  131 + if (Array.isArray(pre[name])) {
  132 + // already array, push to last
  133 + pre[name].push(value);
  134 + } else {
  135 + // single value, make it array
  136 + pre[name] = [pre[name], value];
  137 + }
  138 + } else {
  139 + // not exist, put it
  140 + pre[name] = value;
  141 + }
  142 +
  143 + return pre;
  144 + }, {});
  145 + }
  146 +
  147 + //对img添加额外数据
  148 + if (node.tag === 'img') {
  149 + node.imgIndex = results.images.length;
  150 + var imgUrl = node.attr.src;
  151 + if (imgUrl[0] == '') {
  152 + imgUrl.splice(0, 1);
  153 + }
  154 + imgUrl = wxDiscode.urlToHttpUrl(imgUrl, __placeImgeUrlHttps);
  155 + node.attr.src = imgUrl;
  156 + node.from = bindName;
  157 + results.images.push(node);
  158 + results.imageUrls.push(imgUrl);
  159 + }
  160 +
  161 + // 处理font标签样式属性
  162 + if (node.tag === 'font') {
  163 + var fontSize = ['x-small', 'small', 'medium', 'large', 'x-large', 'xx-large', '-webkit-xxx-large'];
  164 + var styleAttrs = {
  165 + 'color': 'color',
  166 + 'face': 'font-family',
  167 + 'size': 'font-size'
  168 + };
  169 + if (!node.attr.style) node.attr.style = [];
  170 + if (!node.styleStr) node.styleStr = '';
  171 + for (var key in styleAttrs) {
  172 + if (node.attr[key]) {
  173 + var value = key === 'size' ? fontSize[node.attr[key]-1] : node.attr[key];
  174 + node.attr.style.push(styleAttrs[key]);
  175 + node.attr.style.push(value);
  176 + node.styleStr += styleAttrs[key] + ': ' + value + ';';
  177 + }
  178 + }
  179 + }
  180 +
  181 + //临时记录source资源
  182 + if(node.tag === 'source'){
  183 + results.source = node.attr.src;
  184 + }
  185 +
  186 + if (unary) {
  187 + // if this tag doesn't have end tag
  188 + // like <img src="hoge.png"/>
  189 + // add to parents
  190 + var parent = bufArray[0] || results;
  191 + if (parent.nodes === undefined) {
  192 + parent.nodes = [];
  193 + }
  194 + parent.nodes.push(node);
  195 + } else {
  196 + bufArray.unshift(node);
  197 + }
  198 + },
  199 + end: function (tag) {
  200 + //debug(tag);
  201 + // merge into parent tag
  202 + var node = bufArray.shift();
  203 + if (node.tag !== tag) console.error('invalid state: mismatch end tag');
  204 +
  205 + //当有缓存source资源时于于video补上src资源
  206 + if(node.tag === 'video' && results.source){
  207 + node.attr.src = results.source;
  208 + delete results.source;
  209 + }
  210 +
  211 + if (bufArray.length === 0) {
  212 + results.nodes.push(node);
  213 + } else {
  214 + var parent = bufArray[0];
  215 + if (parent.nodes === undefined) {
  216 + parent.nodes = [];
  217 + }
  218 + parent.nodes.push(node);
  219 + }
  220 + },
  221 + chars: function (text) {
  222 + //debug(text);
  223 + var node = {
  224 + node: 'text',
  225 + text: text,
  226 + textArray:transEmojiStr(text)
  227 + };
  228 +
  229 + if (bufArray.length === 0) {
  230 + node.index = index.toString()
  231 + index += 1
  232 + results.nodes.push(node);
  233 + } else {
  234 + var parent = bufArray[0];
  235 + if (parent.nodes === undefined) {
  236 + parent.nodes = [];
  237 + }
  238 + node.index = parent.index + '.' + parent.nodes.length
  239 + parent.nodes.push(node);
  240 + }
  241 + },
  242 + comment: function (text) {
  243 + //debug(text);
  244 + // var node = {
  245 + // node: 'comment',
  246 + // text: text,
  247 + // };
  248 + // var parent = bufArray[0];
  249 + // if (parent.nodes === undefined) {
  250 + // parent.nodes = [];
  251 + // }
  252 + // parent.nodes.push(node);
  253 + },
  254 + });
  255 + return results;
  256 +};
  257 +
  258 +function transEmojiStr(str){
  259 + // var eReg = new RegExp("["+__reg+' '+"]");
  260 +// str = str.replace(/\[([^\[\]]+)\]/g,':$1:')
  261 +
  262 + var emojiObjs = [];
  263 + //如果正则表达式为空
  264 + if(__emojisReg.length == 0 || !__emojis){
  265 + var emojiObj = {}
  266 + emojiObj.node = "text";
  267 + emojiObj.text = str;
  268 + array = [emojiObj];
  269 + return array;
  270 + }
  271 + //这个地方需要调整
  272 + str = str.replace(/\[([^\[\]]+)\]/g,':$1:')
  273 + var eReg = new RegExp("[:]");
  274 + var array = str.split(eReg);
  275 + for(var i = 0; i < array.length; i++){
  276 + var ele = array[i];
  277 + var emojiObj = {};
  278 + if(__emojis[ele]){
  279 + emojiObj.node = "element";
  280 + emojiObj.tag = "emoji";
  281 + emojiObj.text = __emojis[ele];
  282 + emojiObj.baseSrc= __emojisBaseSrc;
  283 + }else{
  284 + emojiObj.node = "text";
  285 + emojiObj.text = ele;
  286 + }
  287 + emojiObjs.push(emojiObj);
  288 + }
  289 +
  290 + return emojiObjs;
  291 +}
  292 +
  293 +function emojisInit(reg='',baseSrc="/wxParse/emojis/",emojis){
  294 + __emojisReg = reg;
  295 + __emojisBaseSrc=baseSrc;
  296 + __emojis=emojis;
  297 +}
  298 +
  299 +module.exports = {
  300 + html2json: html2json,
  301 + emojisInit:emojisInit
  302 +};
  303 +
  1 +/**
  2 + *
  3 + * htmlParser改造自: https://github.com/blowsie/Pure-JavaScript-HTML5-Parser
  4 + *
  5 + * author: Di (微信小程序开发工程师)
  6 + * organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
  7 + * 垂直微信小程序开发交流社区
  8 + *
  9 + * github地址: https://github.com/icindy/wxParse
  10 + *
  11 + * for: 微信小程序富文本解析
  12 + * detail : http://weappdev.com/t/wxparse-alpha0-1-html-markdown/184
  13 + */
  14 +// Regular Expressions for parsing tags and attributes
  15 +var startTag = /^<([-A-Za-z0-9_]+)((?:\s+[a-zA-Z_:][-a-zA-Z0-9_:.]*(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/,
  16 + endTag = /^<\/([-A-Za-z0-9_]+)[^>]*>/,
  17 + attr = /([a-zA-Z_:][-a-zA-Z0-9_:.]*)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g;
  18 +
  19 +// Empty Elements - HTML 5
  20 +var empty = makeMap("area,base,basefont,br,col,frame,hr,img,input,link,meta,param,embed,command,keygen,source,track,wbr");
  21 +
  22 +// Block Elements - HTML 5
  23 +var block = makeMap("a,address,code,article,applet,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,iframe,ins,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video");
  24 +
  25 +// Inline Elements - HTML 5
  26 +var inline = makeMap("abbr,acronym,applet,b,basefont,bdo,big,br,button,cite,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var");
  27 +
  28 +// Elements that you can, intentionally, leave open
  29 +// (and which close themselves)
  30 +var closeSelf = makeMap("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr");
  31 +
  32 +// Attributes that have their values filled in disabled="disabled"
  33 +var fillAttrs = makeMap("checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected");
  34 +
  35 +// Special Elements (can contain anything)
  36 +var special = makeMap("wxxxcode-style,script,style,view,scroll-view,block");
  37 +
  38 +function HTMLParser(html, handler) {
  39 + var index, chars, match, stack = [], last = html;
  40 + stack.last = function () {
  41 + return this[this.length - 1];
  42 + };
  43 +
  44 + while (html) {
  45 + chars = true;
  46 +
  47 + // Make sure we're not in a script or style element
  48 + if (!stack.last() || !special[stack.last()]) {
  49 +
  50 + // Comment
  51 + if (html.indexOf("<!--") == 0) {
  52 + index = html.indexOf("-->");
  53 +
  54 + if (index >= 0) {
  55 + if (handler.comment)
  56 + handler.comment(html.substring(4, index));
  57 + html = html.substring(index + 3);
  58 + chars = false;
  59 + }
  60 +
  61 + // end tag
  62 + } else if (html.indexOf("</") == 0) {
  63 + match = html.match(endTag);
  64 +
  65 + if (match) {
  66 + html = html.substring(match[0].length);
  67 + match[0].replace(endTag, parseEndTag);
  68 + chars = false;
  69 + }
  70 +
  71 + // start tag
  72 + } else if (html.indexOf("<") == 0) {
  73 + match = html.match(startTag);
  74 +
  75 + if (match) {
  76 + html = html.substring(match[0].length);
  77 + match[0].replace(startTag, parseStartTag);
  78 + chars = false;
  79 + }
  80 + }
  81 +
  82 + if (chars) {
  83 + index = html.indexOf("<");
  84 + var text = ''
  85 + while (index === 0) {
  86 + text += "<";
  87 + html = html.substring(1);
  88 + index = html.indexOf("<");
  89 + }
  90 + text += index < 0 ? html : html.substring(0, index);
  91 + html = index < 0 ? "" : html.substring(index);
  92 +
  93 + if (handler.chars)
  94 + handler.chars(text);
  95 + }
  96 +
  97 + } else {
  98 +
  99 + html = html.replace(new RegExp("([\\s\\S]*?)<\/" + stack.last() + "[^>]*>"), function (all, text) {
  100 + text = text.replace(/<!--([\s\S]*?)-->|<!\[CDATA\[([\s\S]*?)]]>/g, "$1$2");
  101 + if (handler.chars)
  102 + handler.chars(text);
  103 +
  104 + return "";
  105 + });
  106 +
  107 +
  108 + parseEndTag("", stack.last());
  109 + }
  110 +
  111 + if (html == last)
  112 + throw "Parse Error: " + html;
  113 + last = html;
  114 + }
  115 +
  116 + // Clean up any remaining tags
  117 + parseEndTag();
  118 +
  119 + function parseStartTag(tag, tagName, rest, unary) {
  120 + tagName = tagName.toLowerCase();
  121 +
  122 + if (block[tagName]) {
  123 + while (stack.last() && inline[stack.last()]) {
  124 + parseEndTag("", stack.last());
  125 + }
  126 + }
  127 +
  128 + if (closeSelf[tagName] && stack.last() == tagName) {
  129 + parseEndTag("", tagName);
  130 + }
  131 +
  132 + unary = empty[tagName] || !!unary;
  133 +
  134 + if (!unary)
  135 + stack.push(tagName);
  136 +
  137 + if (handler.start) {
  138 + var attrs = [];
  139 +
  140 + rest.replace(attr, function (match, name) {
  141 + var value = arguments[2] ? arguments[2] :
  142 + arguments[3] ? arguments[3] :
  143 + arguments[4] ? arguments[4] :
  144 + fillAttrs[name] ? name : "";
  145 +
  146 + attrs.push({
  147 + name: name,
  148 + value: value,
  149 + escaped: value.replace(/(^|[^\\])"/g, '$1\\\"') //"
  150 + });
  151 + });
  152 +
  153 + if (handler.start) {
  154 + handler.start(tagName, attrs, unary);
  155 + }
  156 +
  157 + }
  158 + }
  159 +
  160 + function parseEndTag(tag, tagName) {
  161 + // If no tag name is provided, clean shop
  162 + if (!tagName)
  163 + var pos = 0;
  164 +
  165 + // Find the closest opened tag of the same type
  166 + else {
  167 + tagName = tagName.toLowerCase();
  168 + for (var pos = stack.length - 1; pos >= 0; pos--)
  169 + if (stack[pos] == tagName)
  170 + break;
  171 + }
  172 + if (pos >= 0) {
  173 + // Close all the open elements, up the stack
  174 + for (var i = stack.length - 1; i >= pos; i--)
  175 + if (handler.end)
  176 + handler.end(stack[i]);
  177 +
  178 + // Remove the open elements from the stack
  179 + stack.length = pos;
  180 + }
  181 + }
  182 +};
  183 +
  184 +
  185 +function makeMap(str) {
  186 + var obj = {}, items = str.split(",");
  187 + for (var i = 0; i < items.length; i++)
  188 + obj[items[i]] = true;
  189 + return obj;
  190 +}
  191 +
  192 +module.exports = HTMLParser;
  1 +/**
  2 + *
  3 + * showdown: https://github.com/showdownjs/showdown
  4 + *
  5 + * author: Di (微信小程序开发工程师)
  6 + * organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
  7 + * 垂直微信小程序开发交流社区
  8 + *
  9 + * github地址: https://github.com/icindy/wxParse
  10 + *
  11 + * for: 微信小程序富文本解析
  12 + * detail : http://weappdev.com/t/wxparse-alpha0-1-html-markdown/184
  13 + */
  14 +
  15 +function getDefaultOpts(simple) {
  16 + 'use strict';
  17 +
  18 + var defaultOptions = {
  19 + omitExtraWLInCodeBlocks: {
  20 + defaultValue: false,
  21 + describe: 'Omit the default extra whiteline added to code blocks',
  22 + type: 'boolean'
  23 + },
  24 + noHeaderId: {
  25 + defaultValue: false,
  26 + describe: 'Turn on/off generated header id',
  27 + type: 'boolean'
  28 + },
  29 + prefixHeaderId: {
  30 + defaultValue: false,
  31 + describe: 'Specify a prefix to generated header ids',
  32 + type: 'string'
  33 + },
  34 + headerLevelStart: {
  35 + defaultValue: false,
  36 + describe: 'The header blocks level start',
  37 + type: 'integer'
  38 + },
  39 + parseImgDimensions: {
  40 + defaultValue: false,
  41 + describe: 'Turn on/off image dimension parsing',
  42 + type: 'boolean'
  43 + },
  44 + simplifiedAutoLink: {
  45 + defaultValue: false,
  46 + describe: 'Turn on/off GFM autolink style',
  47 + type: 'boolean'
  48 + },
  49 + literalMidWordUnderscores: {
  50 + defaultValue: false,
  51 + describe: 'Parse midword underscores as literal underscores',
  52 + type: 'boolean'
  53 + },
  54 + strikethrough: {
  55 + defaultValue: false,
  56 + describe: 'Turn on/off strikethrough support',
  57 + type: 'boolean'
  58 + },
  59 + tables: {
  60 + defaultValue: false,
  61 + describe: 'Turn on/off tables support',
  62 + type: 'boolean'
  63 + },
  64 + tablesHeaderId: {
  65 + defaultValue: false,
  66 + describe: 'Add an id to table headers',
  67 + type: 'boolean'
  68 + },
  69 + ghCodeBlocks: {
  70 + defaultValue: true,
  71 + describe: 'Turn on/off GFM fenced code blocks support',
  72 + type: 'boolean'
  73 + },
  74 + tasklists: {
  75 + defaultValue: false,
  76 + describe: 'Turn on/off GFM tasklist support',
  77 + type: 'boolean'
  78 + },
  79 + smoothLivePreview: {
  80 + defaultValue: false,
  81 + describe: 'Prevents weird effects in live previews due to incomplete input',
  82 + type: 'boolean'
  83 + },
  84 + smartIndentationFix: {
  85 + defaultValue: false,
  86 + description: 'Tries to smartly fix identation in es6 strings',
  87 + type: 'boolean'
  88 + }
  89 + };
  90 + if (simple === false) {
  91 + return JSON.parse(JSON.stringify(defaultOptions));
  92 + }
  93 + var ret = {};
  94 + for (var opt in defaultOptions) {
  95 + if (defaultOptions.hasOwnProperty(opt)) {
  96 + ret[opt] = defaultOptions[opt].defaultValue;
  97 + }
  98 + }
  99 + return ret;
  100 +}
  101 +
  102 +/**
  103 + * Created by Tivie on 06-01-2015.
  104 + */
  105 +
  106 +// Private properties
  107 +var showdown = {},
  108 + parsers = {},
  109 + extensions = {},
  110 + globalOptions = getDefaultOpts(true),
  111 + flavor = {
  112 + github: {
  113 + omitExtraWLInCodeBlocks: true,
  114 + prefixHeaderId: 'user-content-',
  115 + simplifiedAutoLink: true,
  116 + literalMidWordUnderscores: true,
  117 + strikethrough: true,
  118 + tables: true,
  119 + tablesHeaderId: true,
  120 + ghCodeBlocks: true,
  121 + tasklists: true
  122 + },
  123 + vanilla: getDefaultOpts(true)
  124 + };
  125 +
  126 +/**
  127 + * helper namespace
  128 + * @type {{}}
  129 + */
  130 +showdown.helper = {};
  131 +
  132 +/**
  133 + * TODO LEGACY SUPPORT CODE
  134 + * @type {{}}
  135 + */
  136 +showdown.extensions = {};
  137 +
  138 +/**
  139 + * Set a global option
  140 + * @static
  141 + * @param {string} key
  142 + * @param {*} value
  143 + * @returns {showdown}
  144 + */
  145 +showdown.setOption = function (key, value) {
  146 + 'use strict';
  147 + globalOptions[key] = value;
  148 + return this;
  149 +};
  150 +
  151 +/**
  152 + * Get a global option
  153 + * @static
  154 + * @param {string} key
  155 + * @returns {*}
  156 + */
  157 +showdown.getOption = function (key) {
  158 + 'use strict';
  159 + return globalOptions[key];
  160 +};
  161 +
  162 +/**
  163 + * Get the global options
  164 + * @static
  165 + * @returns {{}}
  166 + */
  167 +showdown.getOptions = function () {
  168 + 'use strict';
  169 + return globalOptions;
  170 +};
  171 +
  172 +/**
  173 + * Reset global options to the default values
  174 + * @static
  175 + */
  176 +showdown.resetOptions = function () {
  177 + 'use strict';
  178 + globalOptions = getDefaultOpts(true);
  179 +};
  180 +
  181 +/**
  182 + * Set the flavor showdown should use as default
  183 + * @param {string} name
  184 + */
  185 +showdown.setFlavor = function (name) {
  186 + 'use strict';
  187 + if (flavor.hasOwnProperty(name)) {
  188 + var preset = flavor[name];
  189 + for (var option in preset) {
  190 + if (preset.hasOwnProperty(option)) {
  191 + globalOptions[option] = preset[option];
  192 + }
  193 + }
  194 + }
  195 +};
  196 +
  197 +/**
  198 + * Get the default options
  199 + * @static
  200 + * @param {boolean} [simple=true]
  201 + * @returns {{}}
  202 + */
  203 +showdown.getDefaultOptions = function (simple) {
  204 + 'use strict';
  205 + return getDefaultOpts(simple);
  206 +};
  207 +
  208 +/**
  209 + * Get or set a subParser
  210 + *
  211 + * subParser(name) - Get a registered subParser
  212 + * subParser(name, func) - Register a subParser
  213 + * @static
  214 + * @param {string} name
  215 + * @param {function} [func]
  216 + * @returns {*}
  217 + */
  218 +showdown.subParser = function (name, func) {
  219 + 'use strict';
  220 + if (showdown.helper.isString(name)) {
  221 + if (typeof func !== 'undefined') {
  222 + parsers[name] = func;
  223 + } else {
  224 + if (parsers.hasOwnProperty(name)) {
  225 + return parsers[name];
  226 + } else {
  227 + throw Error('SubParser named ' + name + ' not registered!');
  228 + }
  229 + }
  230 + }
  231 +};
  232 +
  233 +/**
  234 + * Gets or registers an extension
  235 + * @static
  236 + * @param {string} name
  237 + * @param {object|function=} ext
  238 + * @returns {*}
  239 + */
  240 +showdown.extension = function (name, ext) {
  241 + 'use strict';
  242 +
  243 + if (!showdown.helper.isString(name)) {
  244 + throw Error('Extension \'name\' must be a string');
  245 + }
  246 +
  247 + name = showdown.helper.stdExtName(name);
  248 +
  249 + // Getter
  250 + if (showdown.helper.isUndefined(ext)) {
  251 + if (!extensions.hasOwnProperty(name)) {
  252 + throw Error('Extension named ' + name + ' is not registered!');
  253 + }
  254 + return extensions[name];
  255 +
  256 + // Setter
  257 + } else {
  258 + // Expand extension if it's wrapped in a function
  259 + if (typeof ext === 'function') {
  260 + ext = ext();
  261 + }
  262 +
  263 + // Ensure extension is an array
  264 + if (!showdown.helper.isArray(ext)) {
  265 + ext = [ext];
  266 + }
  267 +
  268 + var validExtension = validate(ext, name);
  269 +
  270 + if (validExtension.valid) {
  271 + extensions[name] = ext;
  272 + } else {
  273 + throw Error(validExtension.error);
  274 + }
  275 + }
  276 +};
  277 +
  278 +/**
  279 + * Gets all extensions registered
  280 + * @returns {{}}
  281 + */
  282 +showdown.getAllExtensions = function () {
  283 + 'use strict';
  284 + return extensions;
  285 +};
  286 +
  287 +/**
  288 + * Remove an extension
  289 + * @param {string} name
  290 + */
  291 +showdown.removeExtension = function (name) {
  292 + 'use strict';
  293 + delete extensions[name];
  294 +};
  295 +
  296 +/**
  297 + * Removes all extensions
  298 + */
  299 +showdown.resetExtensions = function () {
  300 + 'use strict';
  301 + extensions = {};
  302 +};
  303 +
  304 +/**
  305 + * Validate extension
  306 + * @param {array} extension
  307 + * @param {string} name
  308 + * @returns {{valid: boolean, error: string}}
  309 + */
  310 +function validate(extension, name) {
  311 + 'use strict';
  312 +
  313 + var errMsg = (name) ? 'Error in ' + name + ' extension->' : 'Error in unnamed extension',
  314 + ret = {
  315 + valid: true,
  316 + error: ''
  317 + };
  318 +
  319 + if (!showdown.helper.isArray(extension)) {
  320 + extension = [extension];
  321 + }
  322 +
  323 + for (var i = 0; i < extension.length; ++i) {
  324 + var baseMsg = errMsg + ' sub-extension ' + i + ': ',
  325 + ext = extension[i];
  326 + if (typeof ext !== 'object') {
  327 + ret.valid = false;
  328 + ret.error = baseMsg + 'must be an object, but ' + typeof ext + ' given';
  329 + return ret;
  330 + }
  331 +
  332 + if (!showdown.helper.isString(ext.type)) {
  333 + ret.valid = false;
  334 + ret.error = baseMsg + 'property "type" must be a string, but ' + typeof ext.type + ' given';
  335 + return ret;
  336 + }
  337 +
  338 + var type = ext.type = ext.type.toLowerCase();
  339 +
  340 + // normalize extension type
  341 + if (type === 'language') {
  342 + type = ext.type = 'lang';
  343 + }
  344 +
  345 + if (type === 'html') {
  346 + type = ext.type = 'output';
  347 + }
  348 +
  349 + if (type !== 'lang' && type !== 'output' && type !== 'listener') {
  350 + ret.valid = false;
  351 + ret.error = baseMsg + 'type ' + type + ' is not recognized. Valid values: "lang/language", "output/html" or "listener"';
  352 + return ret;
  353 + }
  354 +
  355 + if (type === 'listener') {
  356 + if (showdown.helper.isUndefined(ext.listeners)) {
  357 + ret.valid = false;
  358 + ret.error = baseMsg + '. Extensions of type "listener" must have a property called "listeners"';
  359 + return ret;
  360 + }
  361 + } else {
  362 + if (showdown.helper.isUndefined(ext.filter) && showdown.helper.isUndefined(ext.regex)) {
  363 + ret.valid = false;
  364 + ret.error = baseMsg + type + ' extensions must define either a "regex" property or a "filter" method';
  365 + return ret;
  366 + }
  367 + }
  368 +
  369 + if (ext.listeners) {
  370 + if (typeof ext.listeners !== 'object') {
  371 + ret.valid = false;
  372 + ret.error = baseMsg + '"listeners" property must be an object but ' + typeof ext.listeners + ' given';
  373 + return ret;
  374 + }
  375 + for (var ln in ext.listeners) {
  376 + if (ext.listeners.hasOwnProperty(ln)) {
  377 + if (typeof ext.listeners[ln] !== 'function') {
  378 + ret.valid = false;
  379 + ret.error = baseMsg + '"listeners" property must be an hash of [event name]: [callback]. listeners.' + ln +
  380 + ' must be a function but ' + typeof ext.listeners[ln] + ' given';
  381 + return ret;
  382 + }
  383 + }
  384 + }
  385 + }
  386 +
  387 + if (ext.filter) {
  388 + if (typeof ext.filter !== 'function') {
  389 + ret.valid = false;
  390 + ret.error = baseMsg + '"filter" must be a function, but ' + typeof ext.filter + ' given';
  391 + return ret;
  392 + }
  393 + } else if (ext.regex) {
  394 + if (showdown.helper.isString(ext.regex)) {
  395 + ext.regex = new RegExp(ext.regex, 'g');
  396 + }
  397 + if (!ext.regex instanceof RegExp) {
  398 + ret.valid = false;
  399 + ret.error = baseMsg + '"regex" property must either be a string or a RegExp object, but ' + typeof ext.regex + ' given';
  400 + return ret;
  401 + }
  402 + if (showdown.helper.isUndefined(ext.replace)) {
  403 + ret.valid = false;
  404 + ret.error = baseMsg + '"regex" extensions must implement a replace string or function';
  405 + return ret;
  406 + }
  407 + }
  408 + }
  409 + return ret;
  410 +}
  411 +
  412 +/**
  413 + * Validate extension
  414 + * @param {object} ext
  415 + * @returns {boolean}
  416 + */
  417 +showdown.validateExtension = function (ext) {
  418 + 'use strict';
  419 +
  420 + var validateExtension = validate(ext, null);
  421 + if (!validateExtension.valid) {
  422 + console.warn(validateExtension.error);
  423 + return false;
  424 + }
  425 + return true;
  426 +};
  427 +
  428 +/**
  429 + * showdownjs helper functions
  430 + */
  431 +
  432 +if (!showdown.hasOwnProperty('helper')) {
  433 + showdown.helper = {};
  434 +}
  435 +
  436 +/**
  437 + * Check if var is string
  438 + * @static
  439 + * @param {string} a
  440 + * @returns {boolean}
  441 + */
  442 +showdown.helper.isString = function isString(a) {
  443 + 'use strict';
  444 + return (typeof a === 'string' || a instanceof String);
  445 +};
  446 +
  447 +/**
  448 + * Check if var is a function
  449 + * @static
  450 + * @param {string} a
  451 + * @returns {boolean}
  452 + */
  453 +showdown.helper.isFunction = function isFunction(a) {
  454 + 'use strict';
  455 + var getType = {};
  456 + return a && getType.toString.call(a) === '[object Function]';
  457 +};
  458 +
  459 +/**
  460 + * ForEach helper function
  461 + * @static
  462 + * @param {*} obj
  463 + * @param {function} callback
  464 + */
  465 +showdown.helper.forEach = function forEach(obj, callback) {
  466 + 'use strict';
  467 + if (typeof obj.forEach === 'function') {
  468 + obj.forEach(callback);
  469 + } else {
  470 + for (var i = 0; i < obj.length; i++) {
  471 + callback(obj[i], i, obj);
  472 + }
  473 + }
  474 +};
  475 +
  476 +/**
  477 + * isArray helper function
  478 + * @static
  479 + * @param {*} a
  480 + * @returns {boolean}
  481 + */
  482 +showdown.helper.isArray = function isArray(a) {
  483 + 'use strict';
  484 + return a.constructor === Array;
  485 +};
  486 +
  487 +/**
  488 + * Check if value is undefined
  489 + * @static
  490 + * @param {*} value The value to check.
  491 + * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
  492 + */
  493 +showdown.helper.isUndefined = function isUndefined(value) {
  494 + 'use strict';
  495 + return typeof value === 'undefined';
  496 +};
  497 +
  498 +/**
  499 + * Standardidize extension name
  500 + * @static
  501 + * @param {string} s extension name
  502 + * @returns {string}
  503 + */
  504 +showdown.helper.stdExtName = function (s) {
  505 + 'use strict';
  506 + return s.replace(/[_-]||\s/g, '').toLowerCase();
  507 +};
  508 +
  509 +function escapeCharactersCallback(wholeMatch, m1) {
  510 + 'use strict';
  511 + var charCodeToEscape = m1.charCodeAt(0);
  512 + return '~E' + charCodeToEscape + 'E';
  513 +}
  514 +
  515 +/**
  516 + * Callback used to escape characters when passing through String.replace
  517 + * @static
  518 + * @param {string} wholeMatch
  519 + * @param {string} m1
  520 + * @returns {string}
  521 + */
  522 +showdown.helper.escapeCharactersCallback = escapeCharactersCallback;
  523 +
  524 +/**
  525 + * Escape characters in a string
  526 + * @static
  527 + * @param {string} text
  528 + * @param {string} charsToEscape
  529 + * @param {boolean} afterBackslash
  530 + * @returns {XML|string|void|*}
  531 + */
  532 +showdown.helper.escapeCharacters = function escapeCharacters(text, charsToEscape, afterBackslash) {
  533 + 'use strict';
  534 + // First we have to escape the escape characters so that
  535 + // we can build a character class out of them
  536 + var regexString = '([' + charsToEscape.replace(/([\[\]\\])/g, '\\$1') + '])';
  537 +
  538 + if (afterBackslash) {
  539 + regexString = '\\\\' + regexString;
  540 + }
  541 +
  542 + var regex = new RegExp(regexString, 'g');
  543 + text = text.replace(regex, escapeCharactersCallback);
  544 +
  545 + return text;
  546 +};
  547 +
  548 +var rgxFindMatchPos = function (str, left, right, flags) {
  549 + 'use strict';
  550 + var f = flags || '',
  551 + g = f.indexOf('g') > -1,
  552 + x = new RegExp(left + '|' + right, 'g' + f.replace(/g/g, '')),
  553 + l = new RegExp(left, f.replace(/g/g, '')),
  554 + pos = [],
  555 + t, s, m, start, end;
  556 +
  557 + do {
  558 + t = 0;
  559 + while ((m = x.exec(str))) {
  560 + if (l.test(m[0])) {
  561 + if (!(t++)) {
  562 + s = x.lastIndex;
  563 + start = s - m[0].length;
  564 + }
  565 + } else if (t) {
  566 + if (!--t) {
  567 + end = m.index + m[0].length;
  568 + var obj = {
  569 + left: {start: start, end: s},
  570 + match: {start: s, end: m.index},
  571 + right: {start: m.index, end: end},
  572 + wholeMatch: {start: start, end: end}
  573 + };
  574 + pos.push(obj);
  575 + if (!g) {
  576 + return pos;
  577 + }
  578 + }
  579 + }
  580 + }
  581 + } while (t && (x.lastIndex = s));
  582 +
  583 + return pos;
  584 +};
  585 +
  586 +/**
  587 + * matchRecursiveRegExp
  588 + *
  589 + * (c) 2007 Steven Levithan <stevenlevithan.com>
  590 + * MIT License
  591 + *
  592 + * Accepts a string to search, a left and right format delimiter
  593 + * as regex patterns, and optional regex flags. Returns an array
  594 + * of matches, allowing nested instances of left/right delimiters.
  595 + * Use the "g" flag to return all matches, otherwise only the
  596 + * first is returned. Be careful to ensure that the left and
  597 + * right format delimiters produce mutually exclusive matches.
  598 + * Backreferences are not supported within the right delimiter
  599 + * due to how it is internally combined with the left delimiter.
  600 + * When matching strings whose format delimiters are unbalanced
  601 + * to the left or right, the output is intentionally as a
  602 + * conventional regex library with recursion support would
  603 + * produce, e.g. "<<x>" and "<x>>" both produce ["x"] when using
  604 + * "<" and ">" as the delimiters (both strings contain a single,
  605 + * balanced instance of "<x>").
  606 + *
  607 + * examples:
  608 + * matchRecursiveRegExp("test", "\\(", "\\)")
  609 + * returns: []
  610 + * matchRecursiveRegExp("<t<<e>><s>>t<>", "<", ">", "g")
  611 + * returns: ["t<<e>><s>", ""]
  612 + * matchRecursiveRegExp("<div id=\"x\">test</div>", "<div\\b[^>]*>", "</div>", "gi")
  613 + * returns: ["test"]
  614 + */
  615 +showdown.helper.matchRecursiveRegExp = function (str, left, right, flags) {
  616 + 'use strict';
  617 +
  618 + var matchPos = rgxFindMatchPos (str, left, right, flags),
  619 + results = [];
  620 +
  621 + for (var i = 0; i < matchPos.length; ++i) {
  622 + results.push([
  623 + str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end),
  624 + str.slice(matchPos[i].match.start, matchPos[i].match.end),
  625 + str.slice(matchPos[i].left.start, matchPos[i].left.end),
  626 + str.slice(matchPos[i].right.start, matchPos[i].right.end)
  627 + ]);
  628 + }
  629 + return results;
  630 +};
  631 +
  632 +/**
  633 + *
  634 + * @param {string} str
  635 + * @param {string|function} replacement
  636 + * @param {string} left
  637 + * @param {string} right
  638 + * @param {string} flags
  639 + * @returns {string}
  640 + */
  641 +showdown.helper.replaceRecursiveRegExp = function (str, replacement, left, right, flags) {
  642 + 'use strict';
  643 +
  644 + if (!showdown.helper.isFunction(replacement)) {
  645 + var repStr = replacement;
  646 + replacement = function () {
  647 + return repStr;
  648 + };
  649 + }
  650 +
  651 + var matchPos = rgxFindMatchPos(str, left, right, flags),
  652 + finalStr = str,
  653 + lng = matchPos.length;
  654 +
  655 + if (lng > 0) {
  656 + var bits = [];
  657 + if (matchPos[0].wholeMatch.start !== 0) {
  658 + bits.push(str.slice(0, matchPos[0].wholeMatch.start));
  659 + }
  660 + for (var i = 0; i < lng; ++i) {
  661 + bits.push(
  662 + replacement(
  663 + str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end),
  664 + str.slice(matchPos[i].match.start, matchPos[i].match.end),
  665 + str.slice(matchPos[i].left.start, matchPos[i].left.end),
  666 + str.slice(matchPos[i].right.start, matchPos[i].right.end)
  667 + )
  668 + );
  669 + if (i < lng - 1) {
  670 + bits.push(str.slice(matchPos[i].wholeMatch.end, matchPos[i + 1].wholeMatch.start));
  671 + }
  672 + }
  673 + if (matchPos[lng - 1].wholeMatch.end < str.length) {
  674 + bits.push(str.slice(matchPos[lng - 1].wholeMatch.end));
  675 + }
  676 + finalStr = bits.join('');
  677 + }
  678 + return finalStr;
  679 +};
  680 +
  681 +/**
  682 + * POLYFILLS
  683 + */
  684 +if (showdown.helper.isUndefined(console)) {
  685 + console = {
  686 + warn: function (msg) {
  687 + 'use strict';
  688 + alert(msg);
  689 + },
  690 + log: function (msg) {
  691 + 'use strict';
  692 + alert(msg);
  693 + },
  694 + error: function (msg) {
  695 + 'use strict';
  696 + throw msg;
  697 + }
  698 + };
  699 +}
  700 +
  701 +/**
  702 + * Created by Estevao on 31-05-2015.
  703 + */
  704 +
  705 +/**
  706 + * Showdown Converter class
  707 + * @class
  708 + * @param {object} [converterOptions]
  709 + * @returns {Converter}
  710 + */
  711 +showdown.Converter = function (converterOptions) {
  712 + 'use strict';
  713 +
  714 + var
  715 + /**
  716 + * Options used by this converter
  717 + * @private
  718 + * @type {{}}
  719 + */
  720 + options = {},
  721 +
  722 + /**
  723 + * Language extensions used by this converter
  724 + * @private
  725 + * @type {Array}
  726 + */
  727 + langExtensions = [],
  728 +
  729 + /**
  730 + * Output modifiers extensions used by this converter
  731 + * @private
  732 + * @type {Array}
  733 + */
  734 + outputModifiers = [],
  735 +
  736 + /**
  737 + * Event listeners
  738 + * @private
  739 + * @type {{}}
  740 + */
  741 + listeners = {};
  742 +
  743 + _constructor();
  744 +
  745 + /**
  746 + * Converter constructor
  747 + * @private
  748 + */
  749 + function _constructor() {
  750 + converterOptions = converterOptions || {};
  751 +
  752 + for (var gOpt in globalOptions) {
  753 + if (globalOptions.hasOwnProperty(gOpt)) {
  754 + options[gOpt] = globalOptions[gOpt];
  755 + }
  756 + }
  757 +
  758 + // Merge options
  759 + if (typeof converterOptions === 'object') {
  760 + for (var opt in converterOptions) {
  761 + if (converterOptions.hasOwnProperty(opt)) {
  762 + options[opt] = converterOptions[opt];
  763 + }
  764 + }
  765 + } else {
  766 + throw Error('Converter expects the passed parameter to be an object, but ' + typeof converterOptions +
  767 + ' was passed instead.');
  768 + }
  769 +
  770 + if (options.extensions) {
  771 + showdown.helper.forEach(options.extensions, _parseExtension);
  772 + }
  773 + }
  774 +
  775 + /**
  776 + * Parse extension
  777 + * @param {*} ext
  778 + * @param {string} [name='']
  779 + * @private
  780 + */
  781 + function _parseExtension(ext, name) {
  782 +
  783 + name = name || null;
  784 + // If it's a string, the extension was previously loaded
  785 + if (showdown.helper.isString(ext)) {
  786 + ext = showdown.helper.stdExtName(ext);
  787 + name = ext;
  788 +
  789 + // LEGACY_SUPPORT CODE
  790 + if (showdown.extensions[ext]) {
  791 + console.warn('DEPRECATION WARNING: ' + ext + ' is an old extension that uses a deprecated loading method.' +
  792 + 'Please inform the developer that the extension should be updated!');
  793 + legacyExtensionLoading(showdown.extensions[ext], ext);
  794 + return;
  795 + // END LEGACY SUPPORT CODE
  796 +
  797 + } else if (!showdown.helper.isUndefined(extensions[ext])) {
  798 + ext = extensions[ext];
  799 +
  800 + } else {
  801 + throw Error('Extension "' + ext + '" could not be loaded. It was either not found or is not a valid extension.');
  802 + }
  803 + }
  804 +
  805 + if (typeof ext === 'function') {
  806 + ext = ext();
  807 + }
  808 +
  809 + if (!showdown.helper.isArray(ext)) {
  810 + ext = [ext];
  811 + }
  812 +
  813 + var validExt = validate(ext, name);
  814 + if (!validExt.valid) {
  815 + throw Error(validExt.error);
  816 + }
  817 +
  818 + for (var i = 0; i < ext.length; ++i) {
  819 + switch (ext[i].type) {
  820 +
  821 + case 'lang':
  822 + langExtensions.push(ext[i]);
  823 + break;
  824 +
  825 + case 'output':
  826 + outputModifiers.push(ext[i]);
  827 + break;
  828 + }
  829 + if (ext[i].hasOwnProperty(listeners)) {
  830 + for (var ln in ext[i].listeners) {
  831 + if (ext[i].listeners.hasOwnProperty(ln)) {
  832 + listen(ln, ext[i].listeners[ln]);
  833 + }
  834 + }
  835 + }
  836 + }
  837 +
  838 + }
  839 +
  840 + /**
  841 + * LEGACY_SUPPORT
  842 + * @param {*} ext
  843 + * @param {string} name
  844 + */
  845 + function legacyExtensionLoading(ext, name) {
  846 + if (typeof ext === 'function') {
  847 + ext = ext(new showdown.Converter());
  848 + }
  849 + if (!showdown.helper.isArray(ext)) {
  850 + ext = [ext];
  851 + }
  852 + var valid = validate(ext, name);
  853 +
  854 + if (!valid.valid) {
  855 + throw Error(valid.error);
  856 + }
  857 +
  858 + for (var i = 0; i < ext.length; ++i) {
  859 + switch (ext[i].type) {
  860 + case 'lang':
  861 + langExtensions.push(ext[i]);
  862 + break;
  863 + case 'output':
  864 + outputModifiers.push(ext[i]);
  865 + break;
  866 + default:// should never reach here
  867 + throw Error('Extension loader error: Type unrecognized!!!');
  868 + }
  869 + }
  870 + }
  871 +
  872 + /**
  873 + * Listen to an event
  874 + * @param {string} name
  875 + * @param {function} callback
  876 + */
  877 + function listen(name, callback) {
  878 + if (!showdown.helper.isString(name)) {
  879 + throw Error('Invalid argument in converter.listen() method: name must be a string, but ' + typeof name + ' given');
  880 + }
  881 +
  882 + if (typeof callback !== 'function') {
  883 + throw Error('Invalid argument in converter.listen() method: callback must be a function, but ' + typeof callback + ' given');
  884 + }
  885 +
  886 + if (!listeners.hasOwnProperty(name)) {
  887 + listeners[name] = [];
  888 + }
  889 + listeners[name].push(callback);
  890 + }
  891 +
  892 + function rTrimInputText(text) {
  893 + var rsp = text.match(/^\s*/)[0].length,
  894 + rgx = new RegExp('^\\s{0,' + rsp + '}', 'gm');
  895 + return text.replace(rgx, '');
  896 + }
  897 +
  898 + /**
  899 + * Dispatch an event
  900 + * @private
  901 + * @param {string} evtName Event name
  902 + * @param {string} text Text
  903 + * @param {{}} options Converter Options
  904 + * @param {{}} globals
  905 + * @returns {string}
  906 + */
  907 + this._dispatch = function dispatch (evtName, text, options, globals) {
  908 + if (listeners.hasOwnProperty(evtName)) {
  909 + for (var ei = 0; ei < listeners[evtName].length; ++ei) {
  910 + var nText = listeners[evtName][ei](evtName, text, this, options, globals);
  911 + if (nText && typeof nText !== 'undefined') {
  912 + text = nText;
  913 + }
  914 + }
  915 + }
  916 + return text;
  917 + };
  918 +
  919 + /**
  920 + * Listen to an event
  921 + * @param {string} name
  922 + * @param {function} callback
  923 + * @returns {showdown.Converter}
  924 + */
  925 + this.listen = function (name, callback) {
  926 + listen(name, callback);
  927 + return this;
  928 + };
  929 +
  930 + /**
  931 + * Converts a markdown string into HTML
  932 + * @param {string} text
  933 + * @returns {*}
  934 + */
  935 + this.makeHtml = function (text) {
  936 + //check if text is not falsy
  937 + if (!text) {
  938 + return text;
  939 + }
  940 +
  941 + var globals = {
  942 + gHtmlBlocks: [],
  943 + gHtmlMdBlocks: [],
  944 + gHtmlSpans: [],
  945 + gUrls: {},
  946 + gTitles: {},
  947 + gDimensions: {},
  948 + gListLevel: 0,
  949 + hashLinkCounts: {},
  950 + langExtensions: langExtensions,
  951 + outputModifiers: outputModifiers,
  952 + converter: this,
  953 + ghCodeBlocks: []
  954 + };
  955 +
  956 + // attacklab: Replace ~ with ~T
  957 + // This lets us use tilde as an escape char to avoid md5 hashes
  958 + // The choice of character is arbitrary; anything that isn't
  959 + // magic in Markdown will work.
  960 + text = text.replace(/~/g, '~T');
  961 +
  962 + // attacklab: Replace $ with ~D
  963 + // RegExp interprets $ as a special character
  964 + // when it's in a replacement string
  965 + text = text.replace(/\$/g, '~D');
  966 +
  967 + // Standardize line endings
  968 + text = text.replace(/\r\n/g, '\n'); // DOS to Unix
  969 + text = text.replace(/\r/g, '\n'); // Mac to Unix
  970 +
  971 + if (options.smartIndentationFix) {
  972 + text = rTrimInputText(text);
  973 + }
  974 +
  975 + // Make sure text begins and ends with a couple of newlines:
  976 + //text = '\n\n' + text + '\n\n';
  977 + text = text;
  978 + // detab
  979 + text = showdown.subParser('detab')(text, options, globals);
  980 +
  981 + // stripBlankLines
  982 + text = showdown.subParser('stripBlankLines')(text, options, globals);
  983 +
  984 + //run languageExtensions
  985 + showdown.helper.forEach(langExtensions, function (ext) {
  986 + text = showdown.subParser('runExtension')(ext, text, options, globals);
  987 + });
  988 +
  989 + // run the sub parsers
  990 + text = showdown.subParser('hashPreCodeTags')(text, options, globals);
  991 + text = showdown.subParser('githubCodeBlocks')(text, options, globals);
  992 + text = showdown.subParser('hashHTMLBlocks')(text, options, globals);
  993 + text = showdown.subParser('hashHTMLSpans')(text, options, globals);
  994 + text = showdown.subParser('stripLinkDefinitions')(text, options, globals);
  995 + text = showdown.subParser('blockGamut')(text, options, globals);
  996 + text = showdown.subParser('unhashHTMLSpans')(text, options, globals);
  997 + text = showdown.subParser('unescapeSpecialChars')(text, options, globals);
  998 +
  999 + // attacklab: Restore dollar signs
  1000 + text = text.replace(/~D/g, '$$');
  1001 +
  1002 + // attacklab: Restore tildes
  1003 + text = text.replace(/~T/g, '~');
  1004 +
  1005 + // Run output modifiers
  1006 + showdown.helper.forEach(outputModifiers, function (ext) {
  1007 + text = showdown.subParser('runExtension')(ext, text, options, globals);
  1008 + });
  1009 + return text;
  1010 + };
  1011 +
  1012 + /**
  1013 + * Set an option of this Converter instance
  1014 + * @param {string} key
  1015 + * @param {*} value
  1016 + */
  1017 + this.setOption = function (key, value) {
  1018 + options[key] = value;
  1019 + };
  1020 +
  1021 + /**
  1022 + * Get the option of this Converter instance
  1023 + * @param {string} key
  1024 + * @returns {*}
  1025 + */
  1026 + this.getOption = function (key) {
  1027 + return options[key];
  1028 + };
  1029 +
  1030 + /**
  1031 + * Get the options of this Converter instance
  1032 + * @returns {{}}
  1033 + */
  1034 + this.getOptions = function () {
  1035 + return options;
  1036 + };
  1037 +
  1038 + /**
  1039 + * Add extension to THIS converter
  1040 + * @param {{}} extension
  1041 + * @param {string} [name=null]
  1042 + */
  1043 + this.addExtension = function (extension, name) {
  1044 + name = name || null;
  1045 + _parseExtension(extension, name);
  1046 + };
  1047 +
  1048 + /**
  1049 + * Use a global registered extension with THIS converter
  1050 + * @param {string} extensionName Name of the previously registered extension
  1051 + */
  1052 + this.useExtension = function (extensionName) {
  1053 + _parseExtension(extensionName);
  1054 + };
  1055 +
  1056 + /**
  1057 + * Set the flavor THIS converter should use
  1058 + * @param {string} name
  1059 + */
  1060 + this.setFlavor = function (name) {
  1061 + if (flavor.hasOwnProperty(name)) {
  1062 + var preset = flavor[name];
  1063 + for (var option in preset) {
  1064 + if (preset.hasOwnProperty(option)) {
  1065 + options[option] = preset[option];
  1066 + }
  1067 + }
  1068 + }
  1069 + };
  1070 +
  1071 + /**
  1072 + * Remove an extension from THIS converter.
  1073 + * Note: This is a costly operation. It's better to initialize a new converter
  1074 + * and specify the extensions you wish to use
  1075 + * @param {Array} extension
  1076 + */
  1077 + this.removeExtension = function (extension) {
  1078 + if (!showdown.helper.isArray(extension)) {
  1079 + extension = [extension];
  1080 + }
  1081 + for (var a = 0; a < extension.length; ++a) {
  1082 + var ext = extension[a];
  1083 + for (var i = 0; i < langExtensions.length; ++i) {
  1084 + if (langExtensions[i] === ext) {
  1085 + langExtensions[i].splice(i, 1);
  1086 + }
  1087 + }
  1088 + for (var ii = 0; ii < outputModifiers.length; ++i) {
  1089 + if (outputModifiers[ii] === ext) {
  1090 + outputModifiers[ii].splice(i, 1);
  1091 + }
  1092 + }
  1093 + }
  1094 + };
  1095 +
  1096 + /**
  1097 + * Get all extension of THIS converter
  1098 + * @returns {{language: Array, output: Array}}
  1099 + */
  1100 + this.getAllExtensions = function () {
  1101 + return {
  1102 + language: langExtensions,
  1103 + output: outputModifiers
  1104 + };
  1105 + };
  1106 +};
  1107 +
  1108 +/**
  1109 + * Turn Markdown link shortcuts into XHTML <a> tags.
  1110 + */
  1111 +showdown.subParser('anchors', function (text, options, globals) {
  1112 + 'use strict';
  1113 +
  1114 + text = globals.converter._dispatch('anchors.before', text, options, globals);
  1115 +
  1116 + var writeAnchorTag = function (wholeMatch, m1, m2, m3, m4, m5, m6, m7) {
  1117 + if (showdown.helper.isUndefined(m7)) {
  1118 + m7 = '';
  1119 + }
  1120 + wholeMatch = m1;
  1121 + var linkText = m2,
  1122 + linkId = m3.toLowerCase(),
  1123 + url = m4,
  1124 + title = m7;
  1125 +
  1126 + if (!url) {
  1127 + if (!linkId) {
  1128 + // lower-case and turn embedded newlines into spaces
  1129 + linkId = linkText.toLowerCase().replace(/ ?\n/g, ' ');
  1130 + }
  1131 + url = '#' + linkId;
  1132 +
  1133 + if (!showdown.helper.isUndefined(globals.gUrls[linkId])) {
  1134 + url = globals.gUrls[linkId];
  1135 + if (!showdown.helper.isUndefined(globals.gTitles[linkId])) {
  1136 + title = globals.gTitles[linkId];
  1137 + }
  1138 + } else {
  1139 + if (wholeMatch.search(/\(\s*\)$/m) > -1) {
  1140 + // Special case for explicit empty url
  1141 + url = '';
  1142 + } else {
  1143 + return wholeMatch;
  1144 + }
  1145 + }
  1146 + }
  1147 +
  1148 + url = showdown.helper.escapeCharacters(url, '*_', false);
  1149 + var result = '<a href="' + url + '"';
  1150 +
  1151 + if (title !== '' && title !== null) {
  1152 + title = title.replace(/"/g, '&quot;');
  1153 + title = showdown.helper.escapeCharacters(title, '*_', false);
  1154 + result += ' title="' + title + '"';
  1155 + }
  1156 +
  1157 + result += '>' + linkText + '</a>';
  1158 +
  1159 + return result;
  1160 + };
  1161 +
  1162 + // First, handle reference-style links: [link text] [id]
  1163 + /*
  1164 + text = text.replace(/
  1165 + ( // wrap whole match in $1
  1166 + \[
  1167 + (
  1168 + (?:
  1169 + \[[^\]]*\] // allow brackets nested one level
  1170 + |
  1171 + [^\[] // or anything else
  1172 + )*
  1173 + )
  1174 + \]
  1175 +
  1176 + [ ]? // one optional space
  1177 + (?:\n[ ]*)? // one optional newline followed by spaces
  1178 +
  1179 + \[
  1180 + (.*?) // id = $3
  1181 + \]
  1182 + )()()()() // pad remaining backreferences
  1183 + /g,_DoAnchors_callback);
  1184 + */
  1185 + text = text.replace(/(\[((?:\[[^\]]*]|[^\[\]])*)][ ]?(?:\n[ ]*)?\[(.*?)])()()()()/g, writeAnchorTag);
  1186 +
  1187 + //
  1188 + // Next, inline-style links: [link text](url "optional title")
  1189 + //
  1190 +
  1191 + /*
  1192 + text = text.replace(/
  1193 + ( // wrap whole match in $1
  1194 + \[
  1195 + (
  1196 + (?:
  1197 + \[[^\]]*\] // allow brackets nested one level
  1198 + |
  1199 + [^\[\]] // or anything else
  1200 + )
  1201 + )
  1202 + \]
  1203 + \( // literal paren
  1204 + [ \t]*
  1205 + () // no id, so leave $3 empty
  1206 + <?(.*?)>? // href = $4
  1207 + [ \t]*
  1208 + ( // $5
  1209 + (['"]) // quote char = $6
  1210 + (.*?) // Title = $7
  1211 + \6 // matching quote
  1212 + [ \t]* // ignore any spaces/tabs between closing quote and )
  1213 + )? // title is optional
  1214 + \)
  1215 + )
  1216 + /g,writeAnchorTag);
  1217 + */
  1218 + text = text.replace(/(\[((?:\[[^\]]*]|[^\[\]])*)]\([ \t]*()<?(.*?(?:\(.*?\).*?)?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,
  1219 + writeAnchorTag);
  1220 +
  1221 + //
  1222 + // Last, handle reference-style shortcuts: [link text]
  1223 + // These must come last in case you've also got [link test][1]
  1224 + // or [link test](/foo)
  1225 + //
  1226 +
  1227 + /*
  1228 + text = text.replace(/
  1229 + ( // wrap whole match in $1
  1230 + \[
  1231 + ([^\[\]]+) // link text = $2; can't contain '[' or ']'
  1232 + \]
  1233 + )()()()()() // pad rest of backreferences
  1234 + /g, writeAnchorTag);
  1235 + */
  1236 + text = text.replace(/(\[([^\[\]]+)])()()()()()/g, writeAnchorTag);
  1237 +
  1238 + text = globals.converter._dispatch('anchors.after', text, options, globals);
  1239 + return text;
  1240 +});
  1241 +
  1242 +showdown.subParser('autoLinks', function (text, options, globals) {
  1243 + 'use strict';
  1244 +
  1245 + text = globals.converter._dispatch('autoLinks.before', text, options, globals);
  1246 +
  1247 + var simpleURLRegex = /\b(((https?|ftp|dict):\/\/|www\.)[^'">\s]+\.[^'">\s]+)(?=\s|$)(?!["<>])/gi,
  1248 + delimUrlRegex = /<(((https?|ftp|dict):\/\/|www\.)[^'">\s]+)>/gi,
  1249 + simpleMailRegex = /(?:^|[ \n\t])([A-Za-z0-9!#$%&'*+-/=?^_`\{|}~\.]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(?:$|[ \n\t])/gi,
  1250 + delimMailRegex = /<(?:mailto:)?([-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi;
  1251 +
  1252 + text = text.replace(delimUrlRegex, replaceLink);
  1253 + text = text.replace(delimMailRegex, replaceMail);
  1254 + // simpleURLRegex = /\b(((https?|ftp|dict):\/\/|www\.)[-.+~:?#@!$&'()*,;=[\]\w]+)\b/gi,
  1255 + // Email addresses: <address@domain.foo>
  1256 +
  1257 + if (options.simplifiedAutoLink) {
  1258 + text = text.replace(simpleURLRegex, replaceLink);
  1259 + text = text.replace(simpleMailRegex, replaceMail);
  1260 + }
  1261 +
  1262 + function replaceLink(wm, link) {
  1263 + var lnkTxt = link;
  1264 + if (/^www\./i.test(link)) {
  1265 + link = link.replace(/^www\./i, 'http://www.');
  1266 + }
  1267 + return '<a href="' + link + '">' + lnkTxt + '</a>';
  1268 + }
  1269 +
  1270 + function replaceMail(wholeMatch, m1) {
  1271 + var unescapedStr = showdown.subParser('unescapeSpecialChars')(m1);
  1272 + return showdown.subParser('encodeEmailAddress')(unescapedStr);
  1273 + }
  1274 +
  1275 + text = globals.converter._dispatch('autoLinks.after', text, options, globals);
  1276 +
  1277 + return text;
  1278 +});
  1279 +
  1280 +/**
  1281 + * These are all the transformations that form block-level
  1282 + * tags like paragraphs, headers, and list items.
  1283 + */
  1284 +showdown.subParser('blockGamut', function (text, options, globals) {
  1285 + 'use strict';
  1286 +
  1287 + text = globals.converter._dispatch('blockGamut.before', text, options, globals);
  1288 +
  1289 + // we parse blockquotes first so that we can have headings and hrs
  1290 + // inside blockquotes
  1291 + text = showdown.subParser('blockQuotes')(text, options, globals);
  1292 + text = showdown.subParser('headers')(text, options, globals);
  1293 +
  1294 + // Do Horizontal Rules:
  1295 + var key = showdown.subParser('hashBlock')('<hr />', options, globals);
  1296 + text = text.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm, key);
  1297 + text = text.replace(/^[ ]{0,2}([ ]?\-[ ]?){3,}[ \t]*$/gm, key);
  1298 + text = text.replace(/^[ ]{0,2}([ ]?_[ ]?){3,}[ \t]*$/gm, key);
  1299 +
  1300 + text = showdown.subParser('lists')(text, options, globals);
  1301 + text = showdown.subParser('codeBlocks')(text, options, globals);
  1302 + text = showdown.subParser('tables')(text, options, globals);
  1303 +
  1304 + // We already ran _HashHTMLBlocks() before, in Markdown(), but that
  1305 + // was to escape raw HTML in the original Markdown source. This time,
  1306 + // we're escaping the markup we've just created, so that we don't wrap
  1307 + // <p> tags around block-level tags.
  1308 + text = showdown.subParser('hashHTMLBlocks')(text, options, globals);
  1309 + text = showdown.subParser('paragraphs')(text, options, globals);
  1310 +
  1311 + text = globals.converter._dispatch('blockGamut.after', text, options, globals);
  1312 +
  1313 + return text;
  1314 +});
  1315 +
  1316 +showdown.subParser('blockQuotes', function (text, options, globals) {
  1317 + 'use strict';
  1318 +
  1319 + text = globals.converter._dispatch('blockQuotes.before', text, options, globals);
  1320 + /*
  1321 + text = text.replace(/
  1322 + ( // Wrap whole match in $1
  1323 + (
  1324 + ^[ \t]*>[ \t]? // '>' at the start of a line
  1325 + .+\n // rest of the first line
  1326 + (.+\n)* // subsequent consecutive lines
  1327 + \n* // blanks
  1328 + )+
  1329 + )
  1330 + /gm, function(){...});
  1331 + */
  1332 +
  1333 + text = text.replace(/((^[ \t]{0,3}>[ \t]?.+\n(.+\n)*\n*)+)/gm, function (wholeMatch, m1) {
  1334 + var bq = m1;
  1335 +
  1336 + // attacklab: hack around Konqueror 3.5.4 bug:
  1337 + // "----------bug".replace(/^-/g,"") == "bug"
  1338 + bq = bq.replace(/^[ \t]*>[ \t]?/gm, '~0'); // trim one level of quoting
  1339 +
  1340 + // attacklab: clean up hack
  1341 + bq = bq.replace(/~0/g, '');
  1342 +
  1343 + bq = bq.replace(/^[ \t]+$/gm, ''); // trim whitespace-only lines
  1344 + bq = showdown.subParser('githubCodeBlocks')(bq, options, globals);
  1345 + bq = showdown.subParser('blockGamut')(bq, options, globals); // recurse
  1346 +
  1347 + bq = bq.replace(/(^|\n)/g, '$1 ');
  1348 + // These leading spaces screw with <pre> content, so we need to fix that:
  1349 + bq = bq.replace(/(\s*<pre>[^\r]+?<\/pre>)/gm, function (wholeMatch, m1) {
  1350 + var pre = m1;
  1351 + // attacklab: hack around Konqueror 3.5.4 bug:
  1352 + pre = pre.replace(/^ /mg, '~0');
  1353 + pre = pre.replace(/~0/g, '');
  1354 + return pre;
  1355 + });
  1356 +
  1357 + return showdown.subParser('hashBlock')('<blockquote>\n' + bq + '\n</blockquote>', options, globals);
  1358 + });
  1359 +
  1360 + text = globals.converter._dispatch('blockQuotes.after', text, options, globals);
  1361 + return text;
  1362 +});
  1363 +
  1364 +/**
  1365 + * Process Markdown `<pre><code>` blocks.
  1366 + */
  1367 +showdown.subParser('codeBlocks', function (text, options, globals) {
  1368 + 'use strict';
  1369 +
  1370 + text = globals.converter._dispatch('codeBlocks.before', text, options, globals);
  1371 + /*
  1372 + text = text.replace(text,
  1373 + /(?:\n\n|^)
  1374 + ( // $1 = the code block -- one or more lines, starting with a space/tab
  1375 + (?:
  1376 + (?:[ ]{4}|\t) // Lines must start with a tab or a tab-width of spaces - attacklab: g_tab_width
  1377 + .*\n+
  1378 + )+
  1379 + )
  1380 + (\n*[ ]{0,3}[^ \t\n]|(?=~0)) // attacklab: g_tab_width
  1381 + /g,function(){...});
  1382 + */
  1383 +
  1384 + // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
  1385 + text += '~0';
  1386 +
  1387 + var pattern = /(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g;
  1388 + text = text.replace(pattern, function (wholeMatch, m1, m2) {
  1389 + var codeblock = m1,
  1390 + nextChar = m2,
  1391 + end = '\n';
  1392 +
  1393 + codeblock = showdown.subParser('outdent')(codeblock);
  1394 + codeblock = showdown.subParser('encodeCode')(codeblock);
  1395 + codeblock = showdown.subParser('detab')(codeblock);
  1396 + codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines
  1397 + codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing newlines
  1398 +
  1399 + if (options.omitExtraWLInCodeBlocks) {
  1400 + end = '';
  1401 + }
  1402 +
  1403 + codeblock = '<pre><code>' + codeblock + end + '</code></pre>';
  1404 +
  1405 + return showdown.subParser('hashBlock')(codeblock, options, globals) + nextChar;
  1406 + });
  1407 +
  1408 + // attacklab: strip sentinel
  1409 + text = text.replace(/~0/, '');
  1410 +
  1411 + text = globals.converter._dispatch('codeBlocks.after', text, options, globals);
  1412 + return text;
  1413 +});
  1414 +
  1415 +/**
  1416 + *
  1417 + * * Backtick quotes are used for <code></code> spans.
  1418 + *
  1419 + * * You can use multiple backticks as the delimiters if you want to
  1420 + * include literal backticks in the code span. So, this input:
  1421 + *
  1422 + * Just type ``foo `bar` baz`` at the prompt.
  1423 + *
  1424 + * Will translate to:
  1425 + *
  1426 + * <p>Just type <code>foo `bar` baz</code> at the prompt.</p>
  1427 + *
  1428 + * There's no arbitrary limit to the number of backticks you
  1429 + * can use as delimters. If you need three consecutive backticks
  1430 + * in your code, use four for delimiters, etc.
  1431 + *
  1432 + * * You can use spaces to get literal backticks at the edges:
  1433 + *
  1434 + * ... type `` `bar` `` ...
  1435 + *
  1436 + * Turns to:
  1437 + *
  1438 + * ... type <code>`bar`</code> ...
  1439 + */
  1440 +showdown.subParser('codeSpans', function (text, options, globals) {
  1441 + 'use strict';
  1442 +
  1443 + text = globals.converter._dispatch('codeSpans.before', text, options, globals);
  1444 +
  1445 + /*
  1446 + text = text.replace(/
  1447 + (^|[^\\]) // Character before opening ` can't be a backslash
  1448 + (`+) // $2 = Opening run of `
  1449 + ( // $3 = The code block
  1450 + [^\r]*?
  1451 + [^`] // attacklab: work around lack of lookbehind
  1452 + )
  1453 + \2 // Matching closer
  1454 + (?!`)
  1455 + /gm, function(){...});
  1456 + */
  1457 +
  1458 + if (typeof(text) === 'undefined') {
  1459 + text = '';
  1460 + }
  1461 + text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,
  1462 + function (wholeMatch, m1, m2, m3) {
  1463 + var c = m3;
  1464 + c = c.replace(/^([ \t]*)/g, ''); // leading whitespace
  1465 + c = c.replace(/[ \t]*$/g, ''); // trailing whitespace
  1466 + c = showdown.subParser('encodeCode')(c);
  1467 + return m1 + '<code>' + c + '</code>';
  1468 + }
  1469 + );
  1470 +
  1471 + text = globals.converter._dispatch('codeSpans.after', text, options, globals);
  1472 + return text;
  1473 +});
  1474 +
  1475 +/**
  1476 + * Convert all tabs to spaces
  1477 + */
  1478 +showdown.subParser('detab', function (text) {
  1479 + 'use strict';
  1480 +
  1481 + // expand first n-1 tabs
  1482 + text = text.replace(/\t(?=\t)/g, ' '); // g_tab_width
  1483 +
  1484 + // replace the nth with two sentinels
  1485 + text = text.replace(/\t/g, '~A~B');
  1486 +
  1487 + // use the sentinel to anchor our regex so it doesn't explode
  1488 + text = text.replace(/~B(.+?)~A/g, function (wholeMatch, m1) {
  1489 + var leadingText = m1,
  1490 + numSpaces = 4 - leadingText.length % 4; // g_tab_width
  1491 +
  1492 + // there *must* be a better way to do this:
  1493 + for (var i = 0; i < numSpaces; i++) {
  1494 + leadingText += ' ';
  1495 + }
  1496 +
  1497 + return leadingText;
  1498 + });
  1499 +
  1500 + // clean up sentinels
  1501 + text = text.replace(/~A/g, ' '); // g_tab_width
  1502 + text = text.replace(/~B/g, '');
  1503 +
  1504 + return text;
  1505 +
  1506 +});
  1507 +
  1508 +/**
  1509 + * Smart processing for ampersands and angle brackets that need to be encoded.
  1510 + */
  1511 +showdown.subParser('encodeAmpsAndAngles', function (text) {
  1512 + 'use strict';
  1513 + // Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin:
  1514 + // http://bumppo.net/projects/amputator/
  1515 + text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g, '&amp;');
  1516 +
  1517 + // Encode naked <'s
  1518 + text = text.replace(/<(?![a-z\/?\$!])/gi, '&lt;');
  1519 +
  1520 + return text;
  1521 +});
  1522 +
  1523 +/**
  1524 + * Returns the string, with after processing the following backslash escape sequences.
  1525 + *
  1526 + * attacklab: The polite way to do this is with the new escapeCharacters() function:
  1527 + *
  1528 + * text = escapeCharacters(text,"\\",true);
  1529 + * text = escapeCharacters(text,"`*_{}[]()>#+-.!",true);
  1530 + *
  1531 + * ...but we're sidestepping its use of the (slow) RegExp constructor
  1532 + * as an optimization for Firefox. This function gets called a LOT.
  1533 + */
  1534 +showdown.subParser('encodeBackslashEscapes', function (text) {
  1535 + 'use strict';
  1536 + text = text.replace(/\\(\\)/g, showdown.helper.escapeCharactersCallback);
  1537 + text = text.replace(/\\([`*_{}\[\]()>#+-.!])/g, showdown.helper.escapeCharactersCallback);
  1538 + return text;
  1539 +});
  1540 +
  1541 +/**
  1542 + * Encode/escape certain characters inside Markdown code runs.
  1543 + * The point is that in code, these characters are literals,
  1544 + * and lose their special Markdown meanings.
  1545 + */
  1546 +showdown.subParser('encodeCode', function (text) {
  1547 + 'use strict';
  1548 +
  1549 + // Encode all ampersands; HTML entities are not
  1550 + // entities within a Markdown code span.
  1551 + text = text.replace(/&/g, '&amp;');
  1552 +
  1553 + // Do the angle bracket song and dance:
  1554 + text = text.replace(/</g, '&lt;');
  1555 + text = text.replace(/>/g, '&gt;');
  1556 +
  1557 + // Now, escape characters that are magic in Markdown:
  1558 + text = showdown.helper.escapeCharacters(text, '*_{}[]\\', false);
  1559 +
  1560 + // jj the line above breaks this:
  1561 + //---
  1562 + //* Item
  1563 + // 1. Subitem
  1564 + // special char: *
  1565 + // ---
  1566 +
  1567 + return text;
  1568 +});
  1569 +
  1570 +/**
  1571 + * Input: an email address, e.g. "foo@example.com"
  1572 + *
  1573 + * Output: the email address as a mailto link, with each character
  1574 + * of the address encoded as either a decimal or hex entity, in
  1575 + * the hopes of foiling most address harvesting spam bots. E.g.:
  1576 + *
  1577 + * <a href="&#x6D;&#97;&#105;&#108;&#x74;&#111;:&#102;&#111;&#111;&#64;&#101;
  1578 + * x&#x61;&#109;&#x70;&#108;&#x65;&#x2E;&#99;&#111;&#109;">&#102;&#111;&#111;
  1579 + * &#64;&#101;x&#x61;&#109;&#x70;&#108;&#x65;&#x2E;&#99;&#111;&#109;</a>
  1580 + *
  1581 + * Based on a filter by Matthew Wickline, posted to the BBEdit-Talk
  1582 + * mailing list: <http://tinyurl.com/yu7ue>
  1583 + *
  1584 + */
  1585 +showdown.subParser('encodeEmailAddress', function (addr) {
  1586 + 'use strict';
  1587 +
  1588 + var encode = [
  1589 + function (ch) {
  1590 + return '&#' + ch.charCodeAt(0) + ';';
  1591 + },
  1592 + function (ch) {
  1593 + return '&#x' + ch.charCodeAt(0).toString(16) + ';';
  1594 + },
  1595 + function (ch) {
  1596 + return ch;
  1597 + }
  1598 + ];
  1599 +
  1600 + addr = 'mailto:' + addr;
  1601 +
  1602 + addr = addr.replace(/./g, function (ch) {
  1603 + if (ch === '@') {
  1604 + // this *must* be encoded. I insist.
  1605 + ch = encode[Math.floor(Math.random() * 2)](ch);
  1606 + } else if (ch !== ':') {
  1607 + // leave ':' alone (to spot mailto: later)
  1608 + var r = Math.random();
  1609 + // roughly 10% raw, 45% hex, 45% dec
  1610 + ch = (
  1611 + r > 0.9 ? encode[2](ch) : r > 0.45 ? encode[1](ch) : encode[0](ch)
  1612 + );
  1613 + }
  1614 + return ch;
  1615 + });
  1616 +
  1617 + addr = '<a href="' + addr + '">' + addr + '</a>';
  1618 + addr = addr.replace(/">.+:/g, '">'); // strip the mailto: from the visible part
  1619 +
  1620 + return addr;
  1621 +});
  1622 +
  1623 +/**
  1624 + * Within tags -- meaning between < and > -- encode [\ ` * _] so they
  1625 + * don't conflict with their use in Markdown for code, italics and strong.
  1626 + */
  1627 +showdown.subParser('escapeSpecialCharsWithinTagAttributes', function (text) {
  1628 + 'use strict';
  1629 +
  1630 + // Build a regex to find HTML tags and comments. See Friedl's
  1631 + // "Mastering Regular Expressions", 2nd Ed., pp. 200-201.
  1632 + var regex = /(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|<!(--.*?--\s*)+>)/gi;
  1633 +
  1634 + text = text.replace(regex, function (wholeMatch) {
  1635 + var tag = wholeMatch.replace(/(.)<\/?code>(?=.)/g, '$1`');
  1636 + tag = showdown.helper.escapeCharacters(tag, '\\`*_', false);
  1637 + return tag;
  1638 + });
  1639 +
  1640 + return text;
  1641 +});
  1642 +
  1643 +/**
  1644 + * Handle github codeblocks prior to running HashHTML so that
  1645 + * HTML contained within the codeblock gets escaped properly
  1646 + * Example:
  1647 + * ```ruby
  1648 + * def hello_world(x)
  1649 + * puts "Hello, #{x}"
  1650 + * end
  1651 + * ```
  1652 + */
  1653 +showdown.subParser('githubCodeBlocks', function (text, options, globals) {
  1654 + 'use strict';
  1655 +
  1656 + // early exit if option is not enabled
  1657 + if (!options.ghCodeBlocks) {
  1658 + return text;
  1659 + }
  1660 +
  1661 + text = globals.converter._dispatch('githubCodeBlocks.before', text, options, globals);
  1662 +
  1663 + text += '~0';
  1664 +
  1665 + text = text.replace(/(?:^|\n)```(.*)\n([\s\S]*?)\n```/g, function (wholeMatch, language, codeblock) {
  1666 + var end = (options.omitExtraWLInCodeBlocks) ? '' : '\n';
  1667 +
  1668 + // First parse the github code block
  1669 + codeblock = showdown.subParser('encodeCode')(codeblock);
  1670 + codeblock = showdown.subParser('detab')(codeblock);
  1671 + codeblock = codeblock.replace(/^\n+/g, ''); // trim leading newlines
  1672 + codeblock = codeblock.replace(/\n+$/g, ''); // trim trailing whitespace
  1673 +
  1674 + codeblock = '<pre><code' + (language ? ' class="' + language + ' language-' + language + '"' : '') + '>' + codeblock + end + '</code></pre>';
  1675 +
  1676 + codeblock = showdown.subParser('hashBlock')(codeblock, options, globals);
  1677 +
  1678 + // Since GHCodeblocks can be false positives, we need to
  1679 + // store the primitive text and the parsed text in a global var,
  1680 + // and then return a token
  1681 + return '\n\n~G' + (globals.ghCodeBlocks.push({text: wholeMatch, codeblock: codeblock}) - 1) + 'G\n\n';
  1682 + });
  1683 +
  1684 + // attacklab: strip sentinel
  1685 + text = text.replace(/~0/, '');
  1686 +
  1687 + return globals.converter._dispatch('githubCodeBlocks.after', text, options, globals);
  1688 +});
  1689 +
  1690 +showdown.subParser('hashBlock', function (text, options, globals) {
  1691 + 'use strict';
  1692 + text = text.replace(/(^\n+|\n+$)/g, '');
  1693 + return '\n\n~K' + (globals.gHtmlBlocks.push(text) - 1) + 'K\n\n';
  1694 +});
  1695 +
  1696 +showdown.subParser('hashElement', function (text, options, globals) {
  1697 + 'use strict';
  1698 +
  1699 + return function (wholeMatch, m1) {
  1700 + var blockText = m1;
  1701 +
  1702 + // Undo double lines
  1703 + blockText = blockText.replace(/\n\n/g, '\n');
  1704 + blockText = blockText.replace(/^\n/, '');
  1705 +
  1706 + // strip trailing blank lines
  1707 + blockText = blockText.replace(/\n+$/g, '');
  1708 +
  1709 + // Replace the element text with a marker ("~KxK" where x is its key)
  1710 + blockText = '\n\n~K' + (globals.gHtmlBlocks.push(blockText) - 1) + 'K\n\n';
  1711 +
  1712 + return blockText;
  1713 + };
  1714 +});
  1715 +
  1716 +showdown.subParser('hashHTMLBlocks', function (text, options, globals) {
  1717 + 'use strict';
  1718 +
  1719 + var blockTags = [
  1720 + 'pre',
  1721 + 'div',
  1722 + 'h1',
  1723 + 'h2',
  1724 + 'h3',
  1725 + 'h4',
  1726 + 'h5',
  1727 + 'h6',
  1728 + 'blockquote',
  1729 + 'table',
  1730 + 'dl',
  1731 + 'ol',
  1732 + 'ul',
  1733 + 'script',
  1734 + 'noscript',
  1735 + 'form',
  1736 + 'fieldset',
  1737 + 'iframe',
  1738 + 'math',
  1739 + 'style',
  1740 + 'section',
  1741 + 'header',
  1742 + 'footer',
  1743 + 'nav',
  1744 + 'article',
  1745 + 'aside',
  1746 + 'address',
  1747 + 'audio',
  1748 + 'canvas',
  1749 + 'figure',
  1750 + 'hgroup',
  1751 + 'output',
  1752 + 'video',
  1753 + 'p'
  1754 + ],
  1755 + repFunc = function (wholeMatch, match, left, right) {
  1756 + var txt = wholeMatch;
  1757 + // check if this html element is marked as markdown
  1758 + // if so, it's contents should be parsed as markdown
  1759 + if (left.search(/\bmarkdown\b/) !== -1) {
  1760 + txt = left + globals.converter.makeHtml(match) + right;
  1761 + }
  1762 + return '\n\n~K' + (globals.gHtmlBlocks.push(txt) - 1) + 'K\n\n';
  1763 + };
  1764 +
  1765 + for (var i = 0; i < blockTags.length; ++i) {
  1766 + text = showdown.helper.replaceRecursiveRegExp(text, repFunc, '^(?: |\\t){0,3}<' + blockTags[i] + '\\b[^>]*>', '</' + blockTags[i] + '>', 'gim');
  1767 + }
  1768 +
  1769 + // HR SPECIAL CASE
  1770 + text = text.replace(/(\n[ ]{0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,
  1771 + showdown.subParser('hashElement')(text, options, globals));
  1772 +
  1773 + // Special case for standalone HTML comments:
  1774 + text = text.replace(/(<!--[\s\S]*?-->)/g,
  1775 + showdown.subParser('hashElement')(text, options, globals));
  1776 +
  1777 + // PHP and ASP-style processor instructions (<?...?> and <%...%>)
  1778 + text = text.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,
  1779 + showdown.subParser('hashElement')(text, options, globals));
  1780 + return text;
  1781 +});
  1782 +
  1783 +/**
  1784 + * Hash span elements that should not be parsed as markdown
  1785 + */
  1786 +showdown.subParser('hashHTMLSpans', function (text, config, globals) {
  1787 + 'use strict';
  1788 +
  1789 + var matches = showdown.helper.matchRecursiveRegExp(text, '<code\\b[^>]*>', '</code>', 'gi');
  1790 +
  1791 + for (var i = 0; i < matches.length; ++i) {
  1792 + text = text.replace(matches[i][0], '~L' + (globals.gHtmlSpans.push(matches[i][0]) - 1) + 'L');
  1793 + }
  1794 + return text;
  1795 +});
  1796 +
  1797 +/**
  1798 + * Unhash HTML spans
  1799 + */
  1800 +showdown.subParser('unhashHTMLSpans', function (text, config, globals) {
  1801 + 'use strict';
  1802 +
  1803 + for (var i = 0; i < globals.gHtmlSpans.length; ++i) {
  1804 + text = text.replace('~L' + i + 'L', globals.gHtmlSpans[i]);
  1805 + }
  1806 +
  1807 + return text;
  1808 +});
  1809 +
  1810 +/**
  1811 + * Hash span elements that should not be parsed as markdown
  1812 + */
  1813 +showdown.subParser('hashPreCodeTags', function (text, config, globals) {
  1814 + 'use strict';
  1815 +
  1816 + var repFunc = function (wholeMatch, match, left, right) {
  1817 + // encode html entities
  1818 + var codeblock = left + showdown.subParser('encodeCode')(match) + right;
  1819 + return '\n\n~G' + (globals.ghCodeBlocks.push({text: wholeMatch, codeblock: codeblock}) - 1) + 'G\n\n';
  1820 + };
  1821 +
  1822 + text = showdown.helper.replaceRecursiveRegExp(text, repFunc, '^(?: |\\t){0,3}<pre\\b[^>]*>\\s*<code\\b[^>]*>', '^(?: |\\t){0,3}</code>\\s*</pre>', 'gim');
  1823 + return text;
  1824 +});
  1825 +
  1826 +showdown.subParser('headers', function (text, options, globals) {
  1827 + 'use strict';
  1828 +
  1829 + text = globals.converter._dispatch('headers.before', text, options, globals);
  1830 +
  1831 + var prefixHeader = options.prefixHeaderId,
  1832 + headerLevelStart = (isNaN(parseInt(options.headerLevelStart))) ? 1 : parseInt(options.headerLevelStart),
  1833 +
  1834 + // Set text-style headers:
  1835 + // Header 1
  1836 + // ========
  1837 + //
  1838 + // Header 2
  1839 + // --------
  1840 + //
  1841 + setextRegexH1 = (options.smoothLivePreview) ? /^(.+)[ \t]*\n={2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n=+[ \t]*\n+/gm,
  1842 + setextRegexH2 = (options.smoothLivePreview) ? /^(.+)[ \t]*\n-{2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n-+[ \t]*\n+/gm;
  1843 +
  1844 + text = text.replace(setextRegexH1, function (wholeMatch, m1) {
  1845 +
  1846 + var spanGamut = showdown.subParser('spanGamut')(m1, options, globals),
  1847 + hID = (options.noHeaderId) ? '' : ' id="' + headerId(m1) + '"',
  1848 + hLevel = headerLevelStart,
  1849 + hashBlock = '<h' + hLevel + hID + '>' + spanGamut + '</h' + hLevel + '>';
  1850 + return showdown.subParser('hashBlock')(hashBlock, options, globals);
  1851 + });
  1852 +
  1853 + text = text.replace(setextRegexH2, function (matchFound, m1) {
  1854 + var spanGamut = showdown.subParser('spanGamut')(m1, options, globals),
  1855 + hID = (options.noHeaderId) ? '' : ' id="' + headerId(m1) + '"',
  1856 + hLevel = headerLevelStart + 1,
  1857 + hashBlock = '<h' + hLevel + hID + '>' + spanGamut + '</h' + hLevel + '>';
  1858 + return showdown.subParser('hashBlock')(hashBlock, options, globals);
  1859 + });
  1860 +
  1861 + // atx-style headers:
  1862 + // # Header 1
  1863 + // ## Header 2
  1864 + // ## Header 2 with closing hashes ##
  1865 + // ...
  1866 + // ###### Header 6
  1867 + //
  1868 + text = text.replace(/^(#{1,6})[ \t]*(.+?)[ \t]*#*\n+/gm, function (wholeMatch, m1, m2) {
  1869 + var span = showdown.subParser('spanGamut')(m2, options, globals),
  1870 + hID = (options.noHeaderId) ? '' : ' id="' + headerId(m2) + '"',
  1871 + hLevel = headerLevelStart - 1 + m1.length,
  1872 + header = '<h' + hLevel + hID + '>' + span + '</h' + hLevel + '>';
  1873 +
  1874 + return showdown.subParser('hashBlock')(header, options, globals);
  1875 + });
  1876 +
  1877 + function headerId(m) {
  1878 + var title, escapedId = m.replace(/[^\w]/g, '').toLowerCase();
  1879 +
  1880 + if (globals.hashLinkCounts[escapedId]) {
  1881 + title = escapedId + '-' + (globals.hashLinkCounts[escapedId]++);
  1882 + } else {
  1883 + title = escapedId;
  1884 + globals.hashLinkCounts[escapedId] = 1;
  1885 + }
  1886 +
  1887 + // Prefix id to prevent causing inadvertent pre-existing style matches.
  1888 + if (prefixHeader === true) {
  1889 + prefixHeader = 'section';
  1890 + }
  1891 +
  1892 + if (showdown.helper.isString(prefixHeader)) {
  1893 + return prefixHeader + title;
  1894 + }
  1895 + return title;
  1896 + }
  1897 +
  1898 + text = globals.converter._dispatch('headers.after', text, options, globals);
  1899 + return text;
  1900 +});
  1901 +
  1902 +/**
  1903 + * Turn Markdown image shortcuts into <img> tags.
  1904 + */
  1905 +showdown.subParser('images', function (text, options, globals) {
  1906 + 'use strict';
  1907 +
  1908 + text = globals.converter._dispatch('images.before', text, options, globals);
  1909 +
  1910 + var inlineRegExp = /!\[(.*?)]\s?\([ \t]*()<?(\S+?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(['"])(.*?)\6[ \t]*)?\)/g,
  1911 + referenceRegExp = /!\[([^\]]*?)] ?(?:\n *)?\[(.*?)]()()()()()/g;
  1912 +
  1913 + function writeImageTag (wholeMatch, altText, linkId, url, width, height, m5, title) {
  1914 +
  1915 + var gUrls = globals.gUrls,
  1916 + gTitles = globals.gTitles,
  1917 + gDims = globals.gDimensions;
  1918 +
  1919 + linkId = linkId.toLowerCase();
  1920 +
  1921 + if (!title) {
  1922 + title = '';
  1923 + }
  1924 +
  1925 + if (url === '' || url === null) {
  1926 + if (linkId === '' || linkId === null) {
  1927 + // lower-case and turn embedded newlines into spaces
  1928 + linkId = altText.toLowerCase().replace(/ ?\n/g, ' ');
  1929 + }
  1930 + url = '#' + linkId;
  1931 +
  1932 + if (!showdown.helper.isUndefined(gUrls[linkId])) {
  1933 + url = gUrls[linkId];
  1934 + if (!showdown.helper.isUndefined(gTitles[linkId])) {
  1935 + title = gTitles[linkId];
  1936 + }
  1937 + if (!showdown.helper.isUndefined(gDims[linkId])) {
  1938 + width = gDims[linkId].width;
  1939 + height = gDims[linkId].height;
  1940 + }
  1941 + } else {
  1942 + return wholeMatch;
  1943 + }
  1944 + }
  1945 +
  1946 + altText = altText.replace(/"/g, '&quot;');
  1947 + altText = showdown.helper.escapeCharacters(altText, '*_', false);
  1948 + url = showdown.helper.escapeCharacters(url, '*_', false);
  1949 + var result = '<img src="' + url + '" alt="' + altText + '"';
  1950 +
  1951 + if (title) {
  1952 + title = title.replace(/"/g, '&quot;');
  1953 + title = showdown.helper.escapeCharacters(title, '*_', false);
  1954 + result += ' title="' + title + '"';
  1955 + }
  1956 +
  1957 + if (width && height) {
  1958 + width = (width === '*') ? 'auto' : width;
  1959 + height = (height === '*') ? 'auto' : height;
  1960 +
  1961 + result += ' width="' + width + '"';
  1962 + result += ' height="' + height + '"';
  1963 + }
  1964 +
  1965 + result += ' />';
  1966 + return result;
  1967 + }
  1968 +
  1969 + // First, handle reference-style labeled images: ![alt text][id]
  1970 + text = text.replace(referenceRegExp, writeImageTag);
  1971 +
  1972 + // Next, handle inline images: ![alt text](url =<width>x<height> "optional title")
  1973 + text = text.replace(inlineRegExp, writeImageTag);
  1974 +
  1975 + text = globals.converter._dispatch('images.after', text, options, globals);
  1976 + return text;
  1977 +});
  1978 +
  1979 +showdown.subParser('italicsAndBold', function (text, options, globals) {
  1980 + 'use strict';
  1981 +
  1982 + text = globals.converter._dispatch('italicsAndBold.before', text, options, globals);
  1983 +
  1984 + if (options.literalMidWordUnderscores) {
  1985 + //underscores
  1986 + // Since we are consuming a \s character, we need to add it
  1987 + text = text.replace(/(^|\s|>|\b)__(?=\S)([\s\S]+?)__(?=\b|<|\s|$)/gm, '$1<strong>$2</strong>');
  1988 + text = text.replace(/(^|\s|>|\b)_(?=\S)([\s\S]+?)_(?=\b|<|\s|$)/gm, '$1<em>$2</em>');
  1989 + //asterisks
  1990 + text = text.replace(/(\*\*)(?=\S)([^\r]*?\S[*]*)\1/g, '<strong>$2</strong>');
  1991 + text = text.replace(/(\*)(?=\S)([^\r]*?\S)\1/g, '<em>$2</em>');
  1992 +
  1993 + } else {
  1994 + // <strong> must go first:
  1995 + text = text.replace(/(\*\*|__)(?=\S)([^\r]*?\S[*_]*)\1/g, '<strong>$2</strong>');
  1996 + text = text.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g, '<em>$2</em>');
  1997 + }
  1998 +
  1999 + text = globals.converter._dispatch('italicsAndBold.after', text, options, globals);
  2000 + return text;
  2001 +});
  2002 +
  2003 +/**
  2004 + * Form HTML ordered (numbered) and unordered (bulleted) lists.
  2005 + */
  2006 +showdown.subParser('lists', function (text, options, globals) {
  2007 + 'use strict';
  2008 +
  2009 + text = globals.converter._dispatch('lists.before', text, options, globals);
  2010 + /**
  2011 + * Process the contents of a single ordered or unordered list, splitting it
  2012 + * into individual list items.
  2013 + * @param {string} listStr
  2014 + * @param {boolean} trimTrailing
  2015 + * @returns {string}
  2016 + */
  2017 + function processListItems (listStr, trimTrailing) {
  2018 + // The $g_list_level global keeps track of when we're inside a list.
  2019 + // Each time we enter a list, we increment it; when we leave a list,
  2020 + // we decrement. If it's zero, we're not in a list anymore.
  2021 + //
  2022 + // We do this because when we're not inside a list, we want to treat
  2023 + // something like this:
  2024 + //
  2025 + // I recommend upgrading to version
  2026 + // 8. Oops, now this line is treated
  2027 + // as a sub-list.
  2028 + //
  2029 + // As a single paragraph, despite the fact that the second line starts
  2030 + // with a digit-period-space sequence.
  2031 + //
  2032 + // Whereas when we're inside a list (or sub-list), that line will be
  2033 + // treated as the start of a sub-list. What a kludge, huh? This is
  2034 + // an aspect of Markdown's syntax that's hard to parse perfectly
  2035 + // without resorting to mind-reading. Perhaps the solution is to
  2036 + // change the syntax rules such that sub-lists must start with a
  2037 + // starting cardinal number; e.g. "1." or "a.".
  2038 + globals.gListLevel++;
  2039 +
  2040 + // trim trailing blank lines:
  2041 + listStr = listStr.replace(/\n{2,}$/, '\n');
  2042 +
  2043 + // attacklab: add sentinel to emulate \z
  2044 + listStr += '~0';
  2045 +
  2046 + var rgx = /(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm,
  2047 + isParagraphed = (/\n[ \t]*\n(?!~0)/.test(listStr));
  2048 +
  2049 + listStr = listStr.replace(rgx, function (wholeMatch, m1, m2, m3, m4, taskbtn, checked) {
  2050 + checked = (checked && checked.trim() !== '');
  2051 + var item = showdown.subParser('outdent')(m4, options, globals),
  2052 + bulletStyle = '';
  2053 +
  2054 + // Support for github tasklists
  2055 + if (taskbtn && options.tasklists) {
  2056 + bulletStyle = ' class="task-list-item" style="list-style-type: none;"';
  2057 + item = item.replace(/^[ \t]*\[(x|X| )?]/m, function () {
  2058 + var otp = '<input type="checkbox" disabled style="margin: 0px 0.35em 0.25em -1.6em; vertical-align: middle;"';
  2059 + if (checked) {
  2060 + otp += ' checked';
  2061 + }
  2062 + otp += '>';
  2063 + return otp;
  2064 + });
  2065 + }
  2066 + // m1 - Leading line or
  2067 + // Has a double return (multi paragraph) or
  2068 + // Has sublist
  2069 + if (m1 || (item.search(/\n{2,}/) > -1)) {
  2070 + item = showdown.subParser('githubCodeBlocks')(item, options, globals);
  2071 + item = showdown.subParser('blockGamut')(item, options, globals);
  2072 + } else {
  2073 + // Recursion for sub-lists:
  2074 + item = showdown.subParser('lists')(item, options, globals);
  2075 + item = item.replace(/\n$/, ''); // chomp(item)
  2076 + if (isParagraphed) {
  2077 + item = showdown.subParser('paragraphs')(item, options, globals);
  2078 + } else {
  2079 + item = showdown.subParser('spanGamut')(item, options, globals);
  2080 + }
  2081 + }
  2082 + item = '\n<li' + bulletStyle + '>' + item + '</li>\n';
  2083 + return item;
  2084 + });
  2085 +
  2086 + // attacklab: strip sentinel
  2087 + listStr = listStr.replace(/~0/g, '');
  2088 +
  2089 + globals.gListLevel--;
  2090 +
  2091 + if (trimTrailing) {
  2092 + listStr = listStr.replace(/\s+$/, '');
  2093 + }
  2094 +
  2095 + return listStr;
  2096 + }
  2097 +
  2098 + /**
  2099 + * Check and parse consecutive lists (better fix for issue #142)
  2100 + * @param {string} list
  2101 + * @param {string} listType
  2102 + * @param {boolean} trimTrailing
  2103 + * @returns {string}
  2104 + */
  2105 + function parseConsecutiveLists(list, listType, trimTrailing) {
  2106 + // check if we caught 2 or more consecutive lists by mistake
  2107 + // we use the counterRgx, meaning if listType is UL we look for UL and vice versa
  2108 + var counterRxg = (listType === 'ul') ? /^ {0,2}\d+\.[ \t]/gm : /^ {0,2}[*+-][ \t]/gm,
  2109 + subLists = [],
  2110 + result = '';
  2111 +
  2112 + if (list.search(counterRxg) !== -1) {
  2113 + (function parseCL(txt) {
  2114 + var pos = txt.search(counterRxg);
  2115 + if (pos !== -1) {
  2116 + // slice
  2117 + result += '\n\n<' + listType + '>' + processListItems(txt.slice(0, pos), !!trimTrailing) + '</' + listType + '>\n\n';
  2118 +
  2119 + // invert counterType and listType
  2120 + listType = (listType === 'ul') ? 'ol' : 'ul';
  2121 + counterRxg = (listType === 'ul') ? /^ {0,2}\d+\.[ \t]/gm : /^ {0,2}[*+-][ \t]/gm;
  2122 +
  2123 + //recurse
  2124 + parseCL(txt.slice(pos));
  2125 + } else {
  2126 + result += '\n\n<' + listType + '>' + processListItems(txt, !!trimTrailing) + '</' + listType + '>\n\n';
  2127 + }
  2128 + })(list);
  2129 + for (var i = 0; i < subLists.length; ++i) {
  2130 +
  2131 + }
  2132 + } else {
  2133 + result = '\n\n<' + listType + '>' + processListItems(list, !!trimTrailing) + '</' + listType + '>\n\n';
  2134 + }
  2135 +
  2136 + return result;
  2137 + }
  2138 +
  2139 + // attacklab: add sentinel to hack around khtml/safari bug:
  2140 + // http://bugs.webkit.org/show_bug.cgi?id=11231
  2141 + text += '~0';
  2142 +
  2143 + // Re-usable pattern to match any entire ul or ol list:
  2144 + var wholeList = /^(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm;
  2145 +
  2146 + if (globals.gListLevel) {
  2147 + text = text.replace(wholeList, function (wholeMatch, list, m2) {
  2148 + var listType = (m2.search(/[*+-]/g) > -1) ? 'ul' : 'ol';
  2149 + return parseConsecutiveLists(list, listType, true);
  2150 + });
  2151 + } else {
  2152 + wholeList = /(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm;
  2153 + //wholeList = /(\n\n|^\n?)( {0,3}([*+-]|\d+\.)[ \t]+[\s\S]+?)(?=(~0)|(\n\n(?!\t| {2,}| {0,3}([*+-]|\d+\.)[ \t])))/g;
  2154 + text = text.replace(wholeList, function (wholeMatch, m1, list, m3) {
  2155 +
  2156 + var listType = (m3.search(/[*+-]/g) > -1) ? 'ul' : 'ol';
  2157 + return parseConsecutiveLists(list, listType);
  2158 + });
  2159 + }
  2160 +
  2161 + // attacklab: strip sentinel
  2162 + text = text.replace(/~0/, '');
  2163 +
  2164 + text = globals.converter._dispatch('lists.after', text, options, globals);
  2165 + return text;
  2166 +});
  2167 +
  2168 +/**
  2169 + * Remove one level of line-leading tabs or spaces
  2170 + */
  2171 +showdown.subParser('outdent', function (text) {
  2172 + 'use strict';
  2173 +
  2174 + // attacklab: hack around Konqueror 3.5.4 bug:
  2175 + // "----------bug".replace(/^-/g,"") == "bug"
  2176 + text = text.replace(/^(\t|[ ]{1,4})/gm, '~0'); // attacklab: g_tab_width
  2177 +
  2178 + // attacklab: clean up hack
  2179 + text = text.replace(/~0/g, '');
  2180 +
  2181 + return text;
  2182 +});
  2183 +
  2184 +/**
  2185 + *
  2186 + */
  2187 +showdown.subParser('paragraphs', function (text, options, globals) {
  2188 + 'use strict';
  2189 +
  2190 + text = globals.converter._dispatch('paragraphs.before', text, options, globals);
  2191 + // Strip leading and trailing lines:
  2192 + text = text.replace(/^\n+/g, '');
  2193 + text = text.replace(/\n+$/g, '');
  2194 +
  2195 + var grafs = text.split(/\n{2,}/g),
  2196 + grafsOut = [],
  2197 + end = grafs.length; // Wrap <p> tags
  2198 +
  2199 + for (var i = 0; i < end; i++) {
  2200 + var str = grafs[i];
  2201 + // if this is an HTML marker, copy it
  2202 + if (str.search(/~(K|G)(\d+)\1/g) >= 0) {
  2203 + grafsOut.push(str);
  2204 + } else {
  2205 + str = showdown.subParser('spanGamut')(str, options, globals);
  2206 + str = str.replace(/^([ \t]*)/g, '<p>');
  2207 + str += '</p>';
  2208 + grafsOut.push(str);
  2209 + }
  2210 + }
  2211 +
  2212 + /** Unhashify HTML blocks */
  2213 + end = grafsOut.length;
  2214 + for (i = 0; i < end; i++) {
  2215 + var blockText = '',
  2216 + grafsOutIt = grafsOut[i],
  2217 + codeFlag = false;
  2218 + // if this is a marker for an html block...
  2219 + while (grafsOutIt.search(/~(K|G)(\d+)\1/) >= 0) {
  2220 + var delim = RegExp.$1,
  2221 + num = RegExp.$2;
  2222 +
  2223 + if (delim === 'K') {
  2224 + blockText = globals.gHtmlBlocks[num];
  2225 + } else {
  2226 + // we need to check if ghBlock is a false positive
  2227 + if (codeFlag) {
  2228 + // use encoded version of all text
  2229 + blockText = showdown.subParser('encodeCode')(globals.ghCodeBlocks[num].text);
  2230 + } else {
  2231 + blockText = globals.ghCodeBlocks[num].codeblock;
  2232 + }
  2233 + }
  2234 + blockText = blockText.replace(/\$/g, '$$$$'); // Escape any dollar signs
  2235 +
  2236 + grafsOutIt = grafsOutIt.replace(/(\n\n)?~(K|G)\d+\2(\n\n)?/, blockText);
  2237 + // Check if grafsOutIt is a pre->code
  2238 + if (/^<pre\b[^>]*>\s*<code\b[^>]*>/.test(grafsOutIt)) {
  2239 + codeFlag = true;
  2240 + }
  2241 + }
  2242 + grafsOut[i] = grafsOutIt;
  2243 + }
  2244 + text = grafsOut.join('\n\n');
  2245 + // Strip leading and trailing lines:
  2246 + text = text.replace(/^\n+/g, '');
  2247 + text = text.replace(/\n+$/g, '');
  2248 + return globals.converter._dispatch('paragraphs.after', text, options, globals);
  2249 +});
  2250 +
  2251 +/**
  2252 + * Run extension
  2253 + */
  2254 +showdown.subParser('runExtension', function (ext, text, options, globals) {
  2255 + 'use strict';
  2256 +
  2257 + if (ext.filter) {
  2258 + text = ext.filter(text, globals.converter, options);
  2259 +
  2260 + } else if (ext.regex) {
  2261 + // TODO remove this when old extension loading mechanism is deprecated
  2262 + var re = ext.regex;
  2263 + if (!re instanceof RegExp) {
  2264 + re = new RegExp(re, 'g');
  2265 + }
  2266 + text = text.replace(re, ext.replace);
  2267 + }
  2268 +
  2269 + return text;
  2270 +});
  2271 +
  2272 +/**
  2273 + * These are all the transformations that occur *within* block-level
  2274 + * tags like paragraphs, headers, and list items.
  2275 + */
  2276 +showdown.subParser('spanGamut', function (text, options, globals) {
  2277 + 'use strict';
  2278 +
  2279 + text = globals.converter._dispatch('spanGamut.before', text, options, globals);
  2280 + text = showdown.subParser('codeSpans')(text, options, globals);
  2281 + text = showdown.subParser('escapeSpecialCharsWithinTagAttributes')(text, options, globals);
  2282 + text = showdown.subParser('encodeBackslashEscapes')(text, options, globals);
  2283 +
  2284 + // Process anchor and image tags. Images must come first,
  2285 + // because ![foo][f] looks like an anchor.
  2286 + text = showdown.subParser('images')(text, options, globals);
  2287 + text = showdown.subParser('anchors')(text, options, globals);
  2288 +
  2289 + // Make links out of things like `<http://example.com/>`
  2290 + // Must come after _DoAnchors(), because you can use < and >
  2291 + // delimiters in inline links like [this](<url>).
  2292 + text = showdown.subParser('autoLinks')(text, options, globals);
  2293 + text = showdown.subParser('encodeAmpsAndAngles')(text, options, globals);
  2294 + text = showdown.subParser('italicsAndBold')(text, options, globals);
  2295 + text = showdown.subParser('strikethrough')(text, options, globals);
  2296 +
  2297 + // Do hard breaks:
  2298 + text = text.replace(/ +\n/g, ' <br />\n');
  2299 +
  2300 + text = globals.converter._dispatch('spanGamut.after', text, options, globals);
  2301 + return text;
  2302 +});
  2303 +
  2304 +showdown.subParser('strikethrough', function (text, options, globals) {
  2305 + 'use strict';
  2306 +
  2307 + if (options.strikethrough) {
  2308 + text = globals.converter._dispatch('strikethrough.before', text, options, globals);
  2309 + text = text.replace(/(?:~T){2}([\s\S]+?)(?:~T){2}/g, '<del>$1</del>');
  2310 + text = globals.converter._dispatch('strikethrough.after', text, options, globals);
  2311 + }
  2312 +
  2313 + return text;
  2314 +});
  2315 +
  2316 +/**
  2317 + * Strip any lines consisting only of spaces and tabs.
  2318 + * This makes subsequent regexs easier to write, because we can
  2319 + * match consecutive blank lines with /\n+/ instead of something
  2320 + * contorted like /[ \t]*\n+/
  2321 + */
  2322 +showdown.subParser('stripBlankLines', function (text) {
  2323 + 'use strict';
  2324 + return text.replace(/^[ \t]+$/mg, '');
  2325 +});
  2326 +
  2327 +/**
  2328 + * Strips link definitions from text, stores the URLs and titles in
  2329 + * hash references.
  2330 + * Link defs are in the form: ^[id]: url "optional title"
  2331 + *
  2332 + * ^[ ]{0,3}\[(.+)\]: // id = $1 attacklab: g_tab_width - 1
  2333 + * [ \t]*
  2334 + * \n? // maybe *one* newline
  2335 + * [ \t]*
  2336 + * <?(\S+?)>? // url = $2
  2337 + * [ \t]*
  2338 + * \n? // maybe one newline
  2339 + * [ \t]*
  2340 + * (?:
  2341 + * (\n*) // any lines skipped = $3 attacklab: lookbehind removed
  2342 + * ["(]
  2343 + * (.+?) // title = $4
  2344 + * [")]
  2345 + * [ \t]*
  2346 + * )? // title is optional
  2347 + * (?:\n+|$)
  2348 + * /gm,
  2349 + * function(){...});
  2350 + *
  2351 + */
  2352 +showdown.subParser('stripLinkDefinitions', function (text, options, globals) {
  2353 + 'use strict';
  2354 +
  2355 + var regex = /^ {0,3}\[(.+)]:[ \t]*\n?[ \t]*<?(\S+?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*\n?[ \t]*(?:(\n*)["|'(](.+?)["|')][ \t]*)?(?:\n+|(?=~0))/gm;
  2356 +
  2357 + // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
  2358 + text += '~0';
  2359 +
  2360 + text = text.replace(regex, function (wholeMatch, linkId, url, width, height, blankLines, title) {
  2361 + linkId = linkId.toLowerCase();
  2362 + globals.gUrls[linkId] = showdown.subParser('encodeAmpsAndAngles')(url); // Link IDs are case-insensitive
  2363 +
  2364 + if (blankLines) {
  2365 + // Oops, found blank lines, so it's not a title.
  2366 + // Put back the parenthetical statement we stole.
  2367 + return blankLines + title;
  2368 +
  2369 + } else {
  2370 + if (title) {
  2371 + globals.gTitles[linkId] = title.replace(/"|'/g, '&quot;');
  2372 + }
  2373 + if (options.parseImgDimensions && width && height) {
  2374 + globals.gDimensions[linkId] = {
  2375 + width: width,
  2376 + height: height
  2377 + };
  2378 + }
  2379 + }
  2380 + // Completely remove the definition from the text
  2381 + return '';
  2382 + });
  2383 +
  2384 + // attacklab: strip sentinel
  2385 + text = text.replace(/~0/, '');
  2386 +
  2387 + return text;
  2388 +});
  2389 +
  2390 +showdown.subParser('tables', function (text, options, globals) {
  2391 + 'use strict';
  2392 +
  2393 + if (!options.tables) {
  2394 + return text;
  2395 + }
  2396 +
  2397 + var tableRgx = /^[ \t]{0,3}\|?.+\|.+\n[ \t]{0,3}\|?[ \t]*:?[ \t]*(?:-|=){2,}[ \t]*:?[ \t]*\|[ \t]*:?[ \t]*(?:-|=){2,}[\s\S]+?(?:\n\n|~0)/gm;
  2398 +
  2399 + function parseStyles(sLine) {
  2400 + if (/^:[ \t]*--*$/.test(sLine)) {
  2401 + return ' style="text-align:left;"';
  2402 + } else if (/^--*[ \t]*:[ \t]*$/.test(sLine)) {
  2403 + return ' style="text-align:right;"';
  2404 + } else if (/^:[ \t]*--*[ \t]*:$/.test(sLine)) {
  2405 + return ' style="text-align:center;"';
  2406 + } else {
  2407 + return '';
  2408 + }
  2409 + }
  2410 +
  2411 + function parseHeaders(header, style) {
  2412 + var id = '';
  2413 + header = header.trim();
  2414 + if (options.tableHeaderId) {
  2415 + id = ' id="' + header.replace(/ /g, '_').toLowerCase() + '"';
  2416 + }
  2417 + header = showdown.subParser('spanGamut')(header, options, globals);
  2418 +
  2419 + return '<th' + id + style + '>' + header + '</th>\n';
  2420 + }
  2421 +
  2422 + function parseCells(cell, style) {
  2423 + var subText = showdown.subParser('spanGamut')(cell, options, globals);
  2424 + return '<td' + style + '>' + subText + '</td>\n';
  2425 + }
  2426 +
  2427 + function buildTable(headers, cells) {
  2428 + var tb = '<table>\n<thead>\n<tr>\n',
  2429 + tblLgn = headers.length;
  2430 +
  2431 + for (var i = 0; i < tblLgn; ++i) {
  2432 + tb += headers[i];
  2433 + }
  2434 + tb += '</tr>\n</thead>\n<tbody>\n';
  2435 +
  2436 + for (i = 0; i < cells.length; ++i) {
  2437 + tb += '<tr>\n';
  2438 + for (var ii = 0; ii < tblLgn; ++ii) {
  2439 + tb += cells[i][ii];
  2440 + }
  2441 + tb += '</tr>\n';
  2442 + }
  2443 + tb += '</tbody>\n</table>\n';
  2444 + return tb;
  2445 + }
  2446 +
  2447 + text = globals.converter._dispatch('tables.before', text, options, globals);
  2448 +
  2449 + text = text.replace(tableRgx, function (rawTable) {
  2450 +
  2451 + var i, tableLines = rawTable.split('\n');
  2452 +
  2453 + // strip wrong first and last column if wrapped tables are used
  2454 + for (i = 0; i < tableLines.length; ++i) {
  2455 + if (/^[ \t]{0,3}\|/.test(tableLines[i])) {
  2456 + tableLines[i] = tableLines[i].replace(/^[ \t]{0,3}\|/, '');
  2457 + }
  2458 + if (/\|[ \t]*$/.test(tableLines[i])) {
  2459 + tableLines[i] = tableLines[i].replace(/\|[ \t]*$/, '');
  2460 + }
  2461 + }
  2462 +
  2463 + var rawHeaders = tableLines[0].split('|').map(function (s) { return s.trim();}),
  2464 + rawStyles = tableLines[1].split('|').map(function (s) { return s.trim();}),
  2465 + rawCells = [],
  2466 + headers = [],
  2467 + styles = [],
  2468 + cells = [];
  2469 +
  2470 + tableLines.shift();
  2471 + tableLines.shift();
  2472 +
  2473 + for (i = 0; i < tableLines.length; ++i) {
  2474 + if (tableLines[i].trim() === '') {
  2475 + continue;
  2476 + }
  2477 + rawCells.push(
  2478 + tableLines[i]
  2479 + .split('|')
  2480 + .map(function (s) {
  2481 + return s.trim();
  2482 + })
  2483 + );
  2484 + }
  2485 +
  2486 + if (rawHeaders.length < rawStyles.length) {
  2487 + return rawTable;
  2488 + }
  2489 +
  2490 + for (i = 0; i < rawStyles.length; ++i) {
  2491 + styles.push(parseStyles(rawStyles[i]));
  2492 + }
  2493 +
  2494 + for (i = 0; i < rawHeaders.length; ++i) {
  2495 + if (showdown.helper.isUndefined(styles[i])) {
  2496 + styles[i] = '';
  2497 + }
  2498 + headers.push(parseHeaders(rawHeaders[i], styles[i]));
  2499 + }
  2500 +
  2501 + for (i = 0; i < rawCells.length; ++i) {
  2502 + var row = [];
  2503 + for (var ii = 0; ii < headers.length; ++ii) {
  2504 + if (showdown.helper.isUndefined(rawCells[i][ii])) {
  2505 +
  2506 + }
  2507 + row.push(parseCells(rawCells[i][ii], styles[ii]));
  2508 + }
  2509 + cells.push(row);
  2510 + }
  2511 +
  2512 + return buildTable(headers, cells);
  2513 + });
  2514 +
  2515 + text = globals.converter._dispatch('tables.after', text, options, globals);
  2516 +
  2517 + return text;
  2518 +});
  2519 +
  2520 +/**
  2521 + * Swap back in all the special characters we've hidden.
  2522 + */
  2523 +showdown.subParser('unescapeSpecialChars', function (text) {
  2524 + 'use strict';
  2525 +
  2526 + text = text.replace(/~E(\d+)E/g, function (wholeMatch, m1) {
  2527 + var charCodeToReplace = parseInt(m1);
  2528 + return String.fromCharCode(charCodeToReplace);
  2529 + });
  2530 + return text;
  2531 +});
  2532 +module.exports = showdown;
  1 +// HTML 支持的数学符号
  2 +function strNumDiscode(str){
  3 + str = str.replace(/&forall;/g, '∀');
  4 + str = str.replace(/&part;/g, '∂');
  5 + str = str.replace(/&exists;/g, '∃');
  6 + str = str.replace(/&empty;/g, '∅');
  7 + str = str.replace(/&nabla;/g, '∇');
  8 + str = str.replace(/&isin;/g, '∈');
  9 + str = str.replace(/&notin;/g, '∉');
  10 + str = str.replace(/&ni;/g, '∋');
  11 + str = str.replace(/&prod;/g, '∏');
  12 + str = str.replace(/&sum;/g, '∑');
  13 + str = str.replace(/&minus;/g, '−');
  14 + str = str.replace(/&lowast;/g, '∗');
  15 + str = str.replace(/&radic;/g, '√');
  16 + str = str.replace(/&prop;/g, '∝');
  17 + str = str.replace(/&infin;/g, '∞');
  18 + str = str.replace(/&ang;/g, '∠');
  19 + str = str.replace(/&and;/g, '∧');
  20 + str = str.replace(/&or;/g, '∨');
  21 + str = str.replace(/&cap;/g, '∩');
  22 + str = str.replace(/&cap;/g, '∪');
  23 + str = str.replace(/&int;/g, '∫');
  24 + str = str.replace(/&there4;/g, '∴');
  25 + str = str.replace(/&sim;/g, '∼');
  26 + str = str.replace(/&cong;/g, '≅');
  27 + str = str.replace(/&asymp;/g, '≈');
  28 + str = str.replace(/&ne;/g, '≠');
  29 + str = str.replace(/&le;/g, '≤');
  30 + str = str.replace(/&ge;/g, '≥');
  31 + str = str.replace(/&sub;/g, '⊂');
  32 + str = str.replace(/&sup;/g, '⊃');
  33 + str = str.replace(/&nsub;/g, '⊄');
  34 + str = str.replace(/&sube;/g, '⊆');
  35 + str = str.replace(/&supe;/g, '⊇');
  36 + str = str.replace(/&oplus;/g, '⊕');
  37 + str = str.replace(/&otimes;/g, '⊗');
  38 + str = str.replace(/&perp;/g, '⊥');
  39 + str = str.replace(/&sdot;/g, '⋅');
  40 + return str;
  41 +}
  42 +
  43 +//HTML 支持的希腊字母
  44 +function strGreeceDiscode(str){
  45 + str = str.replace(/&Alpha;/g, 'Α');
  46 + str = str.replace(/&Beta;/g, 'Β');
  47 + str = str.replace(/&Gamma;/g, 'Γ');
  48 + str = str.replace(/&Delta;/g, 'Δ');
  49 + str = str.replace(/&Epsilon;/g, 'Ε');
  50 + str = str.replace(/&Zeta;/g, 'Ζ');
  51 + str = str.replace(/&Eta;/g, 'Η');
  52 + str = str.replace(/&Theta;/g, 'Θ');
  53 + str = str.replace(/&Iota;/g, 'Ι');
  54 + str = str.replace(/&Kappa;/g, 'Κ');
  55 + str = str.replace(/&Lambda;/g, 'Λ');
  56 + str = str.replace(/&Mu;/g, 'Μ');
  57 + str = str.replace(/&Nu;/g, 'Ν');
  58 + str = str.replace(/&Xi;/g, 'Ν');
  59 + str = str.replace(/&Omicron;/g, 'Ο');
  60 + str = str.replace(/&Pi;/g, 'Π');
  61 + str = str.replace(/&Rho;/g, 'Ρ');
  62 + str = str.replace(/&Sigma;/g, 'Σ');
  63 + str = str.replace(/&Tau;/g, 'Τ');
  64 + str = str.replace(/&Upsilon;/g, 'Υ');
  65 + str = str.replace(/&Phi;/g, 'Φ');
  66 + str = str.replace(/&Chi;/g, 'Χ');
  67 + str = str.replace(/&Psi;/g, 'Ψ');
  68 + str = str.replace(/&Omega;/g, 'Ω');
  69 +
  70 + str = str.replace(/&alpha;/g, 'α');
  71 + str = str.replace(/&beta;/g, 'β');
  72 + str = str.replace(/&gamma;/g, 'γ');
  73 + str = str.replace(/&delta;/g, 'δ');
  74 + str = str.replace(/&epsilon;/g, 'ε');
  75 + str = str.replace(/&zeta;/g, 'ζ');
  76 + str = str.replace(/&eta;/g, 'η');
  77 + str = str.replace(/&theta;/g, 'θ');
  78 + str = str.replace(/&iota;/g, 'ι');
  79 + str = str.replace(/&kappa;/g, 'κ');
  80 + str = str.replace(/&lambda;/g, 'λ');
  81 + str = str.replace(/&mu;/g, 'μ');
  82 + str = str.replace(/&nu;/g, 'ν');
  83 + str = str.replace(/&xi;/g, 'ξ');
  84 + str = str.replace(/&omicron;/g, 'ο');
  85 + str = str.replace(/&pi;/g, 'π');
  86 + str = str.replace(/&rho;/g, 'ρ');
  87 + str = str.replace(/&sigmaf;/g, 'ς');
  88 + str = str.replace(/&sigma;/g, 'σ');
  89 + str = str.replace(/&tau;/g, 'τ');
  90 + str = str.replace(/&upsilon;/g, 'υ');
  91 + str = str.replace(/&phi;/g, 'φ');
  92 + str = str.replace(/&chi;/g, 'χ');
  93 + str = str.replace(/&psi;/g, 'ψ');
  94 + str = str.replace(/&omega;/g, 'ω');
  95 + str = str.replace(/&thetasym;/g, 'ϑ');
  96 + str = str.replace(/&upsih;/g, 'ϒ');
  97 + str = str.replace(/&piv;/g, 'ϖ');
  98 + str = str.replace(/&middot;/g, '·');
  99 + return str;
  100 +}
  101 +
  102 +//
  103 +
  104 +function strcharacterDiscode(str){
  105 + // 加入常用解析
  106 + str = str.replace(/&nbsp;/g, ' ');
  107 + str = str.replace(/&quot;/g, "'");
  108 + str = str.replace(/&amp;/g, '&');
  109 + // str = str.replace(/&lt;/g, '‹');
  110 + // str = str.replace(/&gt;/g, '›');
  111 +
  112 + str = str.replace(/&lt;/g, '<');
  113 + str = str.replace(/&gt;/g, '>');
  114 + str = str.replace(/&#8226;/g, '•');
  115 +
  116 + return str;
  117 +}
  118 +
  119 +// HTML 支持的其他实体
  120 +function strOtherDiscode(str){
  121 + str = str.replace(/&OElig;/g, 'Œ');
  122 + str = str.replace(/&oelig;/g, 'œ');
  123 + str = str.replace(/&Scaron;/g, 'Š');
  124 + str = str.replace(/&scaron;/g, 'š');
  125 + str = str.replace(/&Yuml;/g, 'Ÿ');
  126 + str = str.replace(/&fnof;/g, 'ƒ');
  127 + str = str.replace(/&circ;/g, 'ˆ');
  128 + str = str.replace(/&tilde;/g, '˜');
  129 + str = str.replace(/&ensp;/g, '');
  130 + str = str.replace(/&emsp;/g, '');
  131 + str = str.replace(/&thinsp;/g, '');
  132 + str = str.replace(/&zwnj;/g, '');
  133 + str = str.replace(/&zwj;/g, '');
  134 + str = str.replace(/&lrm;/g, '');
  135 + str = str.replace(/&rlm;/g, '');
  136 + str = str.replace(/&ndash;/g, '–');
  137 + str = str.replace(/&mdash;/g, '—');
  138 + str = str.replace(/&lsquo;/g, '‘');
  139 + str = str.replace(/&rsquo;/g, '’');
  140 + str = str.replace(/&sbquo;/g, '‚');
  141 + str = str.replace(/&ldquo;/g, '“');
  142 + str = str.replace(/&rdquo;/g, '”');
  143 + str = str.replace(/&bdquo;/g, '„');
  144 + str = str.replace(/&dagger;/g, '†');
  145 + str = str.replace(/&Dagger;/g, '‡');
  146 + str = str.replace(/&bull;/g, '•');
  147 + str = str.replace(/&hellip;/g, '…');
  148 + str = str.replace(/&permil;/g, '‰');
  149 + str = str.replace(/&prime;/g, '′');
  150 + str = str.replace(/&Prime;/g, '″');
  151 + str = str.replace(/&lsaquo;/g, '‹');
  152 + str = str.replace(/&rsaquo;/g, '›');
  153 + str = str.replace(/&oline;/g, '‾');
  154 + str = str.replace(/&euro;/g, '€');
  155 + str = str.replace(/&trade;/g, '™');
  156 +
  157 + str = str.replace(/&larr;/g, '←');
  158 + str = str.replace(/&uarr;/g, '↑');
  159 + str = str.replace(/&rarr;/g, '→');
  160 + str = str.replace(/&darr;/g, '↓');
  161 + str = str.replace(/&harr;/g, '↔');
  162 + str = str.replace(/&crarr;/g, '↵');
  163 + str = str.replace(/&lceil;/g, '⌈');
  164 + str = str.replace(/&rceil;/g, '⌉');
  165 +
  166 + str = str.replace(/&lfloor;/g, '⌊');
  167 + str = str.replace(/&rfloor;/g, '⌋');
  168 + str = str.replace(/&loz;/g, '◊');
  169 + str = str.replace(/&spades;/g, '♠');
  170 + str = str.replace(/&clubs;/g, '♣');
  171 + str = str.replace(/&hearts;/g, '♥');
  172 +
  173 + str = str.replace(/&diams;/g, '♦');
  174 + str = str.replace(/&#39;/g, '\'');
  175 + return str;
  176 +}
  177 +
  178 +function strMoreDiscode(str){
  179 + str = str.replace(/\r\n/g,"");
  180 + str = str.replace(/\n/g,"");
  181 +
  182 + str = str.replace(/code/g,"wxxxcode-style");
  183 + return str;
  184 +}
  185 +
  186 +function strDiscode(str){
  187 + str = strNumDiscode(str);
  188 + str = strGreeceDiscode(str);
  189 + str = strcharacterDiscode(str);
  190 + str = strOtherDiscode(str);
  191 + str = strMoreDiscode(str);
  192 + return str;
  193 +}
  194 +function urlToHttpUrl(url,rep){
  195 +
  196 + var patt1 = new RegExp("^//");
  197 + var result = patt1.test(url);
  198 + if(result){
  199 + url = rep+":"+url;
  200 + }
  201 + return url;
  202 +}
  203 +
  204 +module.exports = {
  205 + strDiscode:strDiscode,
  206 + urlToHttpUrl:urlToHttpUrl
  207 +}
  1 +/**
  2 + * author: Di (微信小程序开发工程师)
  3 + * organization: WeAppDev(微信小程序开发论坛)(http://weappdev.com)
  4 + * 垂直微信小程序开发交流社区
  5 + *
  6 + * github地址: https://github.com/icindy/wxParse
  7 + *
  8 + * for: 微信小程序富文本解析
  9 + * detail : http://weappdev.com/t/wxparse-alpha0-1-html-markdown/184
  10 + */
  11 +
  12 +/**
  13 + * utils函数引入
  14 + **/
  15 +import showdown from './showdown.js';
  16 +import HtmlToJson from './html2json.js';
  17 +/**
  18 + * 配置及公有属性
  19 + **/
  20 +var realWindowWidth = 0;
  21 +var realWindowHeight = 0;
  22 +wx.getSystemInfo({
  23 + success: function (res) {
  24 + realWindowWidth = res.windowWidth
  25 + realWindowHeight = res.windowHeight
  26 + }
  27 +})
  28 +/**
  29 + * 主函数入口区
  30 + **/
  31 +function wxParse(bindName = 'wxParseData', type='html', data='<div class="color:red;">数据不能为空</div>', target,imagePadding) {
  32 + var that = target;
  33 + var transData = {};//存放转化后的数据
  34 + if (type == 'html') {
  35 + transData = HtmlToJson.html2json(data, bindName);
  36 + // console.log(JSON.stringify(transData, ' ', ' '));
  37 + } else if (type == 'md' || type == 'markdown') {
  38 + var converter = new showdown.Converter();
  39 + var html = converter.makeHtml(data);
  40 + transData = HtmlToJson.html2json(html, bindName);
  41 + console.log(JSON.stringify(transData, ' ', ' '));
  42 + }
  43 + transData.view = {};
  44 + transData.view.imagePadding = 0;
  45 + if(typeof(imagePadding) != 'undefined'){
  46 + transData.view.imagePadding = imagePadding
  47 + }
  48 + var bindData = {};
  49 + bindData[bindName] = transData;
  50 + that.setData(bindData)
  51 + that.wxParseImgLoad = wxParseImgLoad;
  52 + that.wxParseImgTap = wxParseImgTap;
  53 +}
  54 +// 图片点击事件
  55 +function wxParseImgTap(e) {
  56 + var that = this;
  57 + var nowImgUrl = e.target.dataset.src;
  58 + var tagFrom = e.target.dataset.from;
  59 + if (typeof (tagFrom) != 'undefined' && tagFrom.length > 0) {
  60 + wx.previewImage({
  61 + current: nowImgUrl, // 当前显示图片的http链接
  62 + urls: that.data[tagFrom].imageUrls // 需要预览的图片http链接列表
  63 + })
  64 + }
  65 +}
  66 +
  67 +/**
  68 + * 图片视觉宽高计算函数区
  69 + **/
  70 +function wxParseImgLoad(e) {
  71 + var that = this;
  72 + var tagFrom = e.target.dataset.from;
  73 + var idx = e.target.dataset.idx;
  74 + if (typeof (tagFrom) != 'undefined' && tagFrom.length > 0) {
  75 + calMoreImageInfo(e, idx, that, tagFrom)
  76 + }
  77 +}
  78 +// 假循环获取计算图片视觉最佳宽高
  79 +function calMoreImageInfo(e, idx, that, bindName) {
  80 + var temData = that.data[bindName];
  81 + if (!temData || temData.images.length == 0) {
  82 + return;
  83 + }
  84 + var temImages = temData.images;
  85 + //因为无法获取view宽度 需要自定义padding进行计算,稍后处理
  86 + var recal = wxAutoImageCal(e.detail.width, e.detail.height,that,bindName);
  87 + // temImages[idx].width = recal.imageWidth;
  88 + // temImages[idx].height = recal.imageheight;
  89 + // temData.images = temImages;
  90 + // var bindData = {};
  91 + // bindData[bindName] = temData;
  92 + // that.setData(bindData);
  93 + var index = temImages[idx].index
  94 + var key = `${bindName}`
  95 + for (var i of index.split('.')) key+=`.nodes[${i}]`
  96 + var keyW = key + '.width'
  97 + var keyH = key + '.height'
  98 + that.setData({
  99 + [keyW]: recal.imageWidth,
  100 + [keyH]: recal.imageheight,
  101 + })
  102 +}
  103 +
  104 +// 计算视觉优先的图片宽高
  105 +function wxAutoImageCal(originalWidth, originalHeight,that,bindName) {
  106 + //获取图片的原始长宽
  107 + var windowWidth = 0, windowHeight = 0;
  108 + var autoWidth = 0, autoHeight = 0;
  109 + var results = {};
  110 + var padding = that.data[bindName].view.imagePadding;
  111 + windowWidth = realWindowWidth-2*padding;
  112 + windowHeight = realWindowHeight;
  113 + //判断按照那种方式进行缩放
  114 + // console.log("windowWidth" + windowWidth);
  115 + if (originalWidth > windowWidth) {//在图片width大于手机屏幕width时候
  116 + autoWidth = windowWidth;
  117 + // console.log("autoWidth" + autoWidth);
  118 + autoHeight = (autoWidth * originalHeight) / originalWidth;
  119 + // console.log("autoHeight" + autoHeight);
  120 + results.imageWidth = autoWidth;
  121 + results.imageheight = autoHeight;
  122 + } else {//否则展示原来的数据
  123 + results.imageWidth = originalWidth;
  124 + results.imageheight = originalHeight;
  125 + }
  126 + return results;
  127 +}
  128 +
  129 +function wxParseTemArray(temArrayName,bindNameReg,total,that){
  130 + var array = [];
  131 + var temData = that.data;
  132 + var obj = null;
  133 + for(var i = 0; i < total; i++){
  134 + var simArr = temData[bindNameReg+i].nodes;
  135 + array.push(simArr);
  136 + }
  137 +
  138 + temArrayName = temArrayName || 'wxParseTemArray';
  139 + obj = JSON.parse('{"'+ temArrayName +'":""}');
  140 + obj[temArrayName] = array;
  141 + that.setData(obj);
  142 +}
  143 +
  144 +/**
  145 + * 配置emojis
  146 + *
  147 + */
  148 +
  149 +function emojisInit(reg='',baseSrc="/wxParse/emojis/",emojis){
  150 + HtmlToJson.emojisInit(reg,baseSrc,emojis);
  151 +}
  152 +
  153 +module.exports = {
  154 + wxParse: wxParse,
  155 + wxParseTemArray:wxParseTemArray,
  156 + emojisInit:emojisInit
  157 +}
  158 +
  159 +