xiaoe_mp_npm 1.0.21 → 1.0.22-test02

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/.prettierrc.js +32 -6
  2. package/miniprogram_dist/GoodsItem/index.json +6 -6
  3. package/miniprogram_dist/GoodsItem/index.wxs +18 -18
  4. package/miniprogram_dist/LiveGoodsList/Header/index.js +54 -54
  5. package/miniprogram_dist/LiveGoodsList/Header/index.json +6 -6
  6. package/miniprogram_dist/LiveGoodsList/Header/index.less +45 -45
  7. package/miniprogram_dist/LiveGoodsList/Header/index.scss +105 -105
  8. package/miniprogram_dist/LiveGoodsList/Header/index.wxml +32 -32
  9. package/miniprogram_dist/LiveGoodsList/README.md +9 -9
  10. package/miniprogram_dist/LiveGoodsList/index.json +8 -8
  11. package/miniprogram_dist/LiveGoodsList/index.less +53 -53
  12. package/miniprogram_dist/LiveGoodsList/index.scss +92 -92
  13. package/miniprogram_dist/Task/TaskBubble/index.js +2 -1
  14. package/miniprogram_dist/Task/TaskPopup/component/TaskItem/index.js +241 -166
  15. package/miniprogram_dist/Task/TaskPopup/component/TaskItem/index.scss +26 -0
  16. package/miniprogram_dist/Task/TaskPopup/component/TaskItem/index.wxml +27 -8
  17. package/miniprogram_dist/Task/TaskPopup/component/TaskItem/index.wxss +96 -0
  18. package/miniprogram_dist/Task/TaskPopup/component/TaskList/index.js +4 -0
  19. package/miniprogram_dist/Task/TaskQuizPopup/components/quizContent/index.js +132 -0
  20. package/miniprogram_dist/Task/TaskQuizPopup/components/quizContent/index.json +6 -0
  21. package/miniprogram_dist/Task/TaskQuizPopup/components/quizContent/index.scss +192 -0
  22. package/miniprogram_dist/Task/TaskQuizPopup/components/quizContent/index.wxml +65 -0
  23. package/miniprogram_dist/Task/TaskQuizPopup/components/quizContent/index.wxs +79 -0
  24. package/miniprogram_dist/Task/TaskQuizPopup/components/quizContent/index.wxss +521 -0
  25. package/miniprogram_dist/Task/TaskQuizPopup/components/quizRichText/index.js +47 -0
  26. package/miniprogram_dist/Task/TaskQuizPopup/components/quizRichText/index.json +6 -0
  27. package/miniprogram_dist/Task/TaskQuizPopup/components/quizRichText/index.scss +7 -0
  28. package/miniprogram_dist/Task/TaskQuizPopup/components/quizRichText/index.wxml +2 -0
  29. package/miniprogram_dist/Task/TaskQuizPopup/components/quizRichText/index.wxss +298 -0
  30. package/miniprogram_dist/Task/TaskQuizPopup/components/wxParse/base.wxml +50 -0
  31. package/miniprogram_dist/Task/TaskQuizPopup/components/wxParse/html2json.js +623 -0
  32. package/miniprogram_dist/Task/TaskQuizPopup/components/wxParse/htmlparser.js +183 -0
  33. package/miniprogram_dist/Task/TaskQuizPopup/components/wxParse/iframeParse.js +216 -0
  34. package/miniprogram_dist/Task/TaskQuizPopup/components/wxParse/loop.wxml +3563 -0
  35. package/miniprogram_dist/Task/TaskQuizPopup/components/wxParse/showdown.js +2364 -0
  36. package/miniprogram_dist/Task/TaskQuizPopup/components/wxParse/wxDiscode.js +209 -0
  37. package/miniprogram_dist/Task/TaskQuizPopup/components/wxParse/wxParse.js +269 -0
  38. package/miniprogram_dist/Task/TaskQuizPopup/components/wxParse/wxParse.wxml +1276 -0
  39. package/miniprogram_dist/Task/TaskQuizPopup/components/wxParse/wxParse.wxss +316 -0
  40. package/miniprogram_dist/Task/TaskQuizPopup/index.js +232 -0
  41. package/miniprogram_dist/Task/TaskQuizPopup/index.json +8 -0
  42. package/miniprogram_dist/Task/TaskQuizPopup/index.scss +159 -0
  43. package/miniprogram_dist/Task/TaskQuizPopup/index.wxml +97 -0
  44. package/miniprogram_dist/Task/TaskQuizPopup/index.wxss +478 -0
  45. package/miniprogram_dist/Task/taskQuizRemindPopup/index.js +79 -0
  46. package/miniprogram_dist/Task/taskQuizRemindPopup/index.json +6 -0
  47. package/miniprogram_dist/Task/taskQuizRemindPopup/index.scss +108 -0
  48. package/miniprogram_dist/Task/taskQuizRemindPopup/index.wxml +27 -0
  49. package/miniprogram_dist/Task/taskQuizRemindPopup/index.wxss +286 -0
  50. package/miniprogram_dist/common/utils/tool.js +54 -48
  51. package/package.json +1 -1
  52. package/src/AliveInvite/LiveRoomVertical/index.wxss +252 -252
  53. package/src/CollectionAddress/index.wxss +5 -5
  54. package/src/ConfirmOrder/components/AddressEdit/index.wxss +120 -120
  55. package/src/ConfirmOrder/components/AddressManage/index.wxss +98 -98
  56. package/src/ConfirmOrder/components/AddressSelect/index.wxss +67 -67
  57. package/src/ConfirmOrder/components/ChoosePicker/index.wxss +18 -18
  58. package/src/ConfirmOrder/components/GoodsInfo/components/GoodsCommerce/components/entityGiftList/index.wxss +45 -45
  59. package/src/ConfirmOrder/components/GoodsInfo/components/GoodsCommerce/components/entityItem/index.wxss +100 -100
  60. package/src/ConfirmOrder/components/GoodsInfo/components/GoodsCommerce/index.wxss +55 -55
  61. package/src/ConfirmOrder/components/GoodsInfo/components/ImageData/index.wxss +13 -13
  62. package/src/ConfirmOrder/components/Header/index.wxss +26 -26
  63. package/src/ConfirmOrder/components/IntegralSelect/componenets/integralTips/index.wxss +85 -85
  64. package/src/ConfirmOrder/components/Invoice/components/InvoiceSelect/index.wxss +155 -155
  65. package/src/ConfirmOrder/components/Invoice/components/InvoiceTip/index.wxss +51 -51
  66. package/src/ConfirmOrder/components/ModeSelect/index.wxss +44 -44
  67. package/src/ConfirmOrder/components/PickupSelect/index.wxss +22 -22
  68. package/src/ConfirmOrder/components/SelectSite/index.wxss +82 -82
  69. package/src/ConfirmOrder/components/Shipper/index.wxss +76 -76
  70. package/src/ConfirmOrder/components/ShipperEdit/index.wxss +78 -78
  71. package/src/ConfirmOrder/components/WechatAddress/index.wxss +22 -22
  72. package/src/ConfirmOrder/index.wxss +5 -5
  73. package/src/CouponList/couponMsg/index.wxss +3 -3
  74. package/src/CustomPopup/index.wxss +22 -22
  75. package/src/GoodsItem/index.json +6 -6
  76. package/src/GoodsItem/index.wxs +18 -18
  77. package/src/LiveGoodsList/Header/index.js +54 -54
  78. package/src/LiveGoodsList/Header/index.json +6 -6
  79. package/src/LiveGoodsList/Header/index.less +45 -45
  80. package/src/LiveGoodsList/Header/index.scss +105 -105
  81. package/src/LiveGoodsList/Header/index.wxml +32 -32
  82. package/src/LiveGoodsList/README.md +9 -9
  83. package/src/LiveGoodsList/index.json +8 -8
  84. package/src/LiveGoodsList/index.less +53 -53
  85. package/src/LiveGoodsList/index.scss +92 -92
  86. package/src/LiveGoodsList/index.wxss +218 -218
  87. package/src/PayComplete/Components/CouponItem/index.wxss +122 -122
  88. package/src/PayComplete/Components/Header/index.wxss +27 -27
  89. package/src/PayComplete/Components/LeadGroup/index.wxss +33 -33
  90. package/src/PayComplete/Components/PayGifts/index.wxss +157 -157
  91. package/src/PayComplete/Components/PayState/earnIntegral/index.wxss +23 -23
  92. package/src/PayComplete/Components/PayState/index.wxss +20 -20
  93. package/src/PayComplete/index.wxss +27 -27
  94. package/src/PayModule/wechatLoading/index.wxss +57 -57
  95. package/src/Recommend/index.wxss +110 -110
  96. package/src/Sku/Header/index.wxss +27 -27
  97. package/src/Sku/goods-info/index.wxss +52 -52
  98. package/src/Sku/index/index.wxss +52 -52
  99. package/src/Sku/row-item/index.wxss +50 -50
  100. package/src/Sku/step/index.wxss +11 -11
  101. package/src/Task/TaskBubble/index.js +2 -1
  102. package/src/Task/TaskBubble/index.wxss +289 -289
  103. package/src/Task/TaskIcon/index.wxss +130 -130
  104. package/src/Task/TaskPopup/component/RewardList/index.wxss +18 -18
  105. package/src/Task/TaskPopup/component/TaskItem/index.js +241 -166
  106. package/src/Task/TaskPopup/component/TaskItem/index.scss +26 -0
  107. package/src/Task/TaskPopup/component/TaskItem/index.wxml +27 -8
  108. package/src/Task/TaskPopup/component/TaskItem/index.wxss +1 -394
  109. package/src/Task/TaskPopup/component/TaskList/index.js +4 -0
  110. package/src/Task/TaskPopup/component/TaskList/index.wxss +118 -118
  111. package/src/Task/TaskPopup/component/TaskType/index.wxss +110 -110
  112. package/src/Task/TaskPopup/index.wxss +406 -406
  113. package/src/Task/TaskQuizPopup/components/quizContent/index.js +132 -0
  114. package/src/Task/TaskQuizPopup/components/quizContent/index.json +6 -0
  115. package/src/Task/TaskQuizPopup/components/quizContent/index.scss +192 -0
  116. package/src/Task/TaskQuizPopup/components/quizContent/index.wxml +65 -0
  117. package/src/Task/TaskQuizPopup/components/quizContent/index.wxs +79 -0
  118. package/src/Task/TaskQuizPopup/components/quizContent/index.wxss +1 -0
  119. package/src/Task/TaskQuizPopup/components/quizRichText/index.js +47 -0
  120. package/src/Task/TaskQuizPopup/components/quizRichText/index.json +6 -0
  121. package/src/Task/TaskQuizPopup/components/quizRichText/index.scss +7 -0
  122. package/src/Task/TaskQuizPopup/components/quizRichText/index.wxml +2 -0
  123. package/src/Task/TaskQuizPopup/components/quizRichText/index.wxss +1 -0
  124. package/src/Task/TaskQuizPopup/components/wxParse/base.wxml +50 -0
  125. package/src/Task/TaskQuizPopup/components/wxParse/html2json.js +623 -0
  126. package/src/Task/TaskQuizPopup/components/wxParse/htmlparser.js +183 -0
  127. package/src/Task/TaskQuizPopup/components/wxParse/iframeParse.js +216 -0
  128. package/src/Task/TaskQuizPopup/components/wxParse/loop.wxml +3563 -0
  129. package/src/Task/TaskQuizPopup/components/wxParse/showdown.js +2364 -0
  130. package/src/Task/TaskQuizPopup/components/wxParse/wxDiscode.js +209 -0
  131. package/src/Task/TaskQuizPopup/components/wxParse/wxParse.js +269 -0
  132. package/src/Task/TaskQuizPopup/components/wxParse/wxParse.wxml +1276 -0
  133. package/src/Task/TaskQuizPopup/components/wxParse/wxParse.wxss +283 -0
  134. package/src/Task/TaskQuizPopup/index.js +232 -0
  135. package/src/Task/TaskQuizPopup/index.json +8 -0
  136. package/src/Task/TaskQuizPopup/index.scss +159 -0
  137. package/src/Task/TaskQuizPopup/index.wxml +97 -0
  138. package/src/Task/TaskQuizPopup/index.wxss +1 -0
  139. package/src/Task/taskQuizRemindPopup/index.js +79 -0
  140. package/src/Task/taskQuizRemindPopup/index.json +6 -0
  141. package/src/Task/taskQuizRemindPopup/index.scss +108 -0
  142. package/src/Task/taskQuizRemindPopup/index.wxml +27 -0
  143. package/src/Task/taskQuizRemindPopup/index.wxss +1 -0
  144. package/src/Task/taskReceivePopup/customPrizes/index.wxss +220 -220
  145. package/src/Task/taskReceivePopup/index.wxss +1 -1
  146. package/src/Task/taskReceivePopup/integral/index.wxss +94 -94
  147. package/src/common/css/theme.wxss +16 -16
  148. package/src/common/utils/tool.js +54 -48
  149. package/src/miniprogram_npm/miniprogram-computed/index.js +1 -0
@@ -0,0 +1,2364 @@
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
+ function getDefaultOpts(simple) {
13
+ 'use strict'
14
+
15
+ var defaultOptions = {
16
+ omitExtraWLInCodeBlocks: {
17
+ defaultValue: false,
18
+ describe: 'Omit the default extra whiteline added to code blocks',
19
+ type: 'boolean',
20
+ },
21
+ noHeaderId: {
22
+ defaultValue: false,
23
+ describe: 'Turn on/off generated header id',
24
+ type: 'boolean',
25
+ },
26
+ prefixHeaderId: {
27
+ defaultValue: false,
28
+ describe: 'Specify a prefix to generated header ids',
29
+ type: 'string',
30
+ },
31
+ headerLevelStart: {
32
+ defaultValue: false,
33
+ describe: 'The header blocks level start',
34
+ type: 'integer',
35
+ },
36
+ parseImgDimensions: {
37
+ defaultValue: false,
38
+ describe: 'Turn on/off image dimension parsing',
39
+ type: 'boolean',
40
+ },
41
+ simplifiedAutoLink: {
42
+ defaultValue: false,
43
+ describe: 'Turn on/off GFM autolink style',
44
+ type: 'boolean',
45
+ },
46
+ literalMidWordUnderscores: {
47
+ defaultValue: false,
48
+ describe: 'Parse midword underscores as literal underscores',
49
+ type: 'boolean',
50
+ },
51
+ strikethrough: {
52
+ defaultValue: false,
53
+ describe: 'Turn on/off strikethrough support',
54
+ type: 'boolean',
55
+ },
56
+ tables: {
57
+ defaultValue: false,
58
+ describe: 'Turn on/off tables support',
59
+ type: 'boolean',
60
+ },
61
+ tablesHeaderId: {
62
+ defaultValue: false,
63
+ describe: 'Add an id to table headers',
64
+ type: 'boolean',
65
+ },
66
+ ghCodeBlocks: {
67
+ defaultValue: true,
68
+ describe: 'Turn on/off GFM fenced code blocks support',
69
+ type: 'boolean',
70
+ },
71
+ tasklists: {
72
+ defaultValue: false,
73
+ describe: 'Turn on/off GFM tasklist support',
74
+ type: 'boolean',
75
+ },
76
+ smoothLivePreview: {
77
+ defaultValue: false,
78
+ describe: 'Prevents weird effects in live previews due to incomplete input',
79
+ type: 'boolean',
80
+ },
81
+ smartIndentationFix: {
82
+ defaultValue: false,
83
+ description: 'Tries to smartly fix identation in es6 strings',
84
+ type: 'boolean',
85
+ },
86
+ }
87
+ if (simple === false) {
88
+ return JSON.parse(JSON.stringify(defaultOptions))
89
+ }
90
+ var ret = {}
91
+ for (var opt in defaultOptions) {
92
+ if (defaultOptions.hasOwnProperty(opt)) {
93
+ ret[opt] = defaultOptions[opt].defaultValue
94
+ }
95
+ }
96
+ return ret
97
+ }
98
+
99
+ /**
100
+ * Created by Tivie on 06-01-2015.
101
+ */
102
+
103
+ // Private properties
104
+ var showdown = {},
105
+ parsers = {},
106
+ extensions = {},
107
+ globalOptions = getDefaultOpts(true),
108
+ flavor = {
109
+ github: {
110
+ omitExtraWLInCodeBlocks: true,
111
+ prefixHeaderId: 'user-content-',
112
+ simplifiedAutoLink: true,
113
+ literalMidWordUnderscores: true,
114
+ strikethrough: true,
115
+ tables: true,
116
+ tablesHeaderId: true,
117
+ ghCodeBlocks: true,
118
+ tasklists: true,
119
+ },
120
+ vanilla: getDefaultOpts(true),
121
+ }
122
+
123
+ /**
124
+ * helper namespace
125
+ * @type {{}}
126
+ */
127
+ showdown.helper = {}
128
+
129
+ /**
130
+ * TODO LEGACY SUPPORT CODE
131
+ * @type {{}}
132
+ */
133
+ showdown.extensions = {}
134
+
135
+ /**
136
+ * Set a global option
137
+ * @static
138
+ * @param {string} key
139
+ * @param {*} value
140
+ * @returns {showdown}
141
+ */
142
+ showdown.setOption = function (key, value) {
143
+ 'use strict'
144
+ globalOptions[key] = value
145
+ return this
146
+ }
147
+
148
+ /**
149
+ * Get a global option
150
+ * @static
151
+ * @param {string} key
152
+ * @returns {*}
153
+ */
154
+ showdown.getOption = function (key) {
155
+ 'use strict'
156
+ return globalOptions[key]
157
+ }
158
+
159
+ /**
160
+ * Get the global options
161
+ * @static
162
+ * @returns {{}}
163
+ */
164
+ showdown.getOptions = function () {
165
+ 'use strict'
166
+ return globalOptions
167
+ }
168
+
169
+ /**
170
+ * Reset global options to the default values
171
+ * @static
172
+ */
173
+ showdown.resetOptions = function () {
174
+ 'use strict'
175
+ globalOptions = getDefaultOpts(true)
176
+ }
177
+
178
+ /**
179
+ * Set the flavor showdown should use as default
180
+ * @param {string} name
181
+ */
182
+ showdown.setFlavor = function (name) {
183
+ 'use strict'
184
+ if (flavor.hasOwnProperty(name)) {
185
+ var preset = flavor[name]
186
+ for (var option in preset) {
187
+ if (preset.hasOwnProperty(option)) {
188
+ globalOptions[option] = preset[option]
189
+ }
190
+ }
191
+ }
192
+ }
193
+
194
+ /**
195
+ * Get the default options
196
+ * @static
197
+ * @param {boolean} [simple=true]
198
+ * @returns {{}}
199
+ */
200
+ showdown.getDefaultOptions = function (simple) {
201
+ 'use strict'
202
+ return getDefaultOpts(simple)
203
+ }
204
+
205
+ /**
206
+ * Get or set a subParser
207
+ *
208
+ * subParser(name) - Get a registered subParser
209
+ * subParser(name, func) - Register a subParser
210
+ * @static
211
+ * @param {string} name
212
+ * @param {function} [func]
213
+ * @returns {*}
214
+ */
215
+ showdown.subParser = function (name, func) {
216
+ 'use strict'
217
+ if (showdown.helper.isString(name)) {
218
+ if (typeof func !== 'undefined') {
219
+ parsers[name] = func
220
+ } else {
221
+ if (parsers.hasOwnProperty(name)) {
222
+ return parsers[name]
223
+ } else {
224
+ throw Error('SubParser named ' + name + ' not registered!')
225
+ }
226
+ }
227
+ }
228
+ }
229
+
230
+ /**
231
+ * Gets or registers an extension
232
+ * @static
233
+ * @param {string} name
234
+ * @param {object|function=} ext
235
+ * @returns {*}
236
+ */
237
+ showdown.extension = function (name, ext) {
238
+ 'use strict'
239
+
240
+ if (!showdown.helper.isString(name)) {
241
+ throw Error("Extension 'name' must be a string")
242
+ }
243
+
244
+ name = showdown.helper.stdExtName(name)
245
+
246
+ // Getter
247
+ if (showdown.helper.isUndefined(ext)) {
248
+ if (!extensions.hasOwnProperty(name)) {
249
+ throw Error('Extension named ' + name + ' is not registered!')
250
+ }
251
+ return extensions[name]
252
+
253
+ // Setter
254
+ } else {
255
+ // Expand extension if it's wrapped in a function
256
+ if (typeof ext === 'function') {
257
+ ext = ext()
258
+ }
259
+
260
+ // Ensure extension is an array
261
+ if (!showdown.helper.isArray(ext)) {
262
+ ext = [ext]
263
+ }
264
+
265
+ var validExtension = validate(ext, name)
266
+
267
+ if (validExtension.valid) {
268
+ extensions[name] = ext
269
+ } else {
270
+ throw Error(validExtension.error)
271
+ }
272
+ }
273
+ }
274
+
275
+ /**
276
+ * Gets all extensions registered
277
+ * @returns {{}}
278
+ */
279
+ showdown.getAllExtensions = function () {
280
+ 'use strict'
281
+ return extensions
282
+ }
283
+
284
+ /**
285
+ * Remove an extension
286
+ * @param {string} name
287
+ */
288
+ showdown.removeExtension = function (name) {
289
+ 'use strict'
290
+ delete extensions[name]
291
+ }
292
+
293
+ /**
294
+ * Removes all extensions
295
+ */
296
+ showdown.resetExtensions = function () {
297
+ 'use strict'
298
+ extensions = {}
299
+ }
300
+
301
+ /**
302
+ * Validate extension
303
+ * @param {array} extension
304
+ * @param {string} name
305
+ * @returns {{valid: boolean, error: string}}
306
+ */
307
+ function validate(extension, name) {
308
+ 'use strict'
309
+
310
+ var errMsg = name ? 'Error in ' + name + ' extension->' : 'Error in unnamed extension',
311
+ ret = {
312
+ valid: true,
313
+ error: '',
314
+ }
315
+
316
+ if (!showdown.helper.isArray(extension)) {
317
+ extension = [extension]
318
+ }
319
+
320
+ for (var i = 0; i < extension.length; ++i) {
321
+ var baseMsg = errMsg + ' sub-extension ' + i + ': ',
322
+ ext = extension[i]
323
+ if (typeof ext !== 'object') {
324
+ ret.valid = false
325
+ ret.error = baseMsg + 'must be an object, but ' + typeof ext + ' given'
326
+ return ret
327
+ }
328
+
329
+ if (!showdown.helper.isString(ext.type)) {
330
+ ret.valid = false
331
+ ret.error = baseMsg + 'property "type" must be a string, but ' + typeof ext.type + ' given'
332
+ return ret
333
+ }
334
+
335
+ var type = (ext.type = ext.type.toLowerCase())
336
+
337
+ // normalize extension type
338
+ if (type === 'language') {
339
+ type = ext.type = 'lang'
340
+ }
341
+
342
+ if (type === 'html') {
343
+ type = ext.type = 'output'
344
+ }
345
+
346
+ if (type !== 'lang' && type !== 'output' && type !== 'listener') {
347
+ ret.valid = false
348
+ ret.error =
349
+ baseMsg + 'type ' + type + ' is not recognized. Valid values: "lang/language", "output/html" or "listener"'
350
+ return ret
351
+ }
352
+
353
+ if (type === 'listener') {
354
+ if (showdown.helper.isUndefined(ext.listeners)) {
355
+ ret.valid = false
356
+ ret.error = baseMsg + '. Extensions of type "listener" must have a property called "listeners"'
357
+ return ret
358
+ }
359
+ } else {
360
+ if (showdown.helper.isUndefined(ext.filter) && showdown.helper.isUndefined(ext.regex)) {
361
+ ret.valid = false
362
+ ret.error = baseMsg + type + ' extensions must define either a "regex" property or a "filter" method'
363
+ return ret
364
+ }
365
+ }
366
+
367
+ if (ext.listeners) {
368
+ if (typeof ext.listeners !== 'object') {
369
+ ret.valid = false
370
+ ret.error = baseMsg + '"listeners" property must be an object but ' + typeof ext.listeners + ' given'
371
+ return ret
372
+ }
373
+ for (var ln in ext.listeners) {
374
+ if (ext.listeners.hasOwnProperty(ln)) {
375
+ if (typeof ext.listeners[ln] !== 'function') {
376
+ ret.valid = false
377
+ ret.error =
378
+ baseMsg +
379
+ '"listeners" property must be an hash of [event name]: [callback]. listeners.' +
380
+ ln +
381
+ ' must be a function but ' +
382
+ typeof ext.listeners[ln] +
383
+ ' given'
384
+ return ret
385
+ }
386
+ }
387
+ }
388
+ }
389
+
390
+ if (ext.filter) {
391
+ if (typeof ext.filter !== 'function') {
392
+ ret.valid = false
393
+ ret.error = baseMsg + '"filter" must be a function, but ' + typeof ext.filter + ' given'
394
+ return ret
395
+ }
396
+ } else if (ext.regex) {
397
+ if (showdown.helper.isString(ext.regex)) {
398
+ ext.regex = new RegExp(ext.regex, 'g')
399
+ }
400
+ if (!ext.regex instanceof RegExp) {
401
+ ret.valid = false
402
+ ret.error =
403
+ baseMsg + '"regex" property must either be a string or a RegExp object, but ' + typeof ext.regex + ' given'
404
+ return ret
405
+ }
406
+ if (showdown.helper.isUndefined(ext.replace)) {
407
+ ret.valid = false
408
+ ret.error = baseMsg + '"regex" extensions must implement a replace string or function'
409
+ return ret
410
+ }
411
+ }
412
+ }
413
+ return ret
414
+ }
415
+
416
+ /**
417
+ * Validate extension
418
+ * @param {object} ext
419
+ * @returns {boolean}
420
+ */
421
+ showdown.validateExtension = function (ext) {
422
+ 'use strict'
423
+
424
+ var validateExtension = validate(ext, null)
425
+ if (!validateExtension.valid) {
426
+ console.warn(validateExtension.error)
427
+ return false
428
+ }
429
+ return true
430
+ }
431
+
432
+ /**
433
+ * showdownjs helper functions
434
+ */
435
+
436
+ if (!showdown.hasOwnProperty('helper')) {
437
+ showdown.helper = {}
438
+ }
439
+
440
+ /**
441
+ * Check if var is string
442
+ * @static
443
+ * @param {string} a
444
+ * @returns {boolean}
445
+ */
446
+ showdown.helper.isString = function isString(a) {
447
+ 'use strict'
448
+ return typeof a === 'string' || a instanceof String
449
+ }
450
+
451
+ /**
452
+ * Check if var is a function
453
+ * @static
454
+ * @param {string} a
455
+ * @returns {boolean}
456
+ */
457
+ showdown.helper.isFunction = function isFunction(a) {
458
+ 'use strict'
459
+ var getType = {}
460
+ return a && getType.toString.call(a) === '[object Function]'
461
+ }
462
+
463
+ /**
464
+ * ForEach helper function
465
+ * @static
466
+ * @param {*} obj
467
+ * @param {function} callback
468
+ */
469
+ showdown.helper.forEach = function forEach(obj, callback) {
470
+ 'use strict'
471
+ if (typeof obj.forEach === 'function') {
472
+ obj.forEach(callback)
473
+ } else {
474
+ for (var i = 0; i < obj.length; i++) {
475
+ callback(obj[i], i, obj)
476
+ }
477
+ }
478
+ }
479
+
480
+ /**
481
+ * isArray helper function
482
+ * @static
483
+ * @param {*} a
484
+ * @returns {boolean}
485
+ */
486
+ showdown.helper.isArray = function isArray(a) {
487
+ 'use strict'
488
+ return a.constructor === Array
489
+ }
490
+
491
+ /**
492
+ * Check if value is undefined
493
+ * @static
494
+ * @param {*} value The value to check.
495
+ * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
496
+ */
497
+ showdown.helper.isUndefined = function isUndefined(value) {
498
+ 'use strict'
499
+ return typeof value === 'undefined'
500
+ }
501
+
502
+ /**
503
+ * Standardidize extension name
504
+ * @static
505
+ * @param {string} s extension name
506
+ * @returns {string}
507
+ */
508
+ showdown.helper.stdExtName = function (s) {
509
+ 'use strict'
510
+ return s.replace(/[_-]||\s/g, '').toLowerCase()
511
+ }
512
+
513
+ function escapeCharactersCallback(wholeMatch, m1) {
514
+ 'use strict'
515
+ var charCodeToEscape = m1.charCodeAt(0)
516
+ return '~E' + charCodeToEscape + 'E'
517
+ }
518
+
519
+ /**
520
+ * Callback used to escape characters when passing through String.replace
521
+ * @static
522
+ * @param {string} wholeMatch
523
+ * @param {string} m1
524
+ * @returns {string}
525
+ */
526
+ showdown.helper.escapeCharactersCallback = escapeCharactersCallback
527
+
528
+ /**
529
+ * Escape characters in a string
530
+ * @static
531
+ * @param {string} text
532
+ * @param {string} charsToEscape
533
+ * @param {boolean} afterBackslash
534
+ * @returns {XML|string|void|*}
535
+ */
536
+ showdown.helper.escapeCharacters = function escapeCharacters(text, charsToEscape, afterBackslash) {
537
+ 'use strict'
538
+ // First we have to escape the escape characters so that
539
+ // we can build a character class out of them
540
+ var regexString = '([' + charsToEscape.replace(/([\[\]\\])/g, '\\$1') + '])'
541
+
542
+ if (afterBackslash) {
543
+ regexString = '\\\\' + regexString
544
+ }
545
+
546
+ var regex = new RegExp(regexString, 'g')
547
+ text = text.replace(regex, escapeCharactersCallback)
548
+
549
+ return text
550
+ }
551
+
552
+ var rgxFindMatchPos = function (str, left, right, flags) {
553
+ 'use strict'
554
+ var f = flags || '',
555
+ g = f.indexOf('g') > -1,
556
+ x = new RegExp(left + '|' + right, 'g' + f.replace(/g/g, '')),
557
+ l = new RegExp(left, f.replace(/g/g, '')),
558
+ pos = [],
559
+ t,
560
+ s,
561
+ m,
562
+ start,
563
+ end
564
+
565
+ do {
566
+ t = 0
567
+ while ((m = x.exec(str))) {
568
+ if (l.test(m[0])) {
569
+ if (!t++) {
570
+ s = x.lastIndex
571
+ start = s - m[0].length
572
+ }
573
+ } else if (t) {
574
+ if (!--t) {
575
+ end = m.index + m[0].length
576
+ var obj = {
577
+ left: { start: start, end: s },
578
+ match: { start: s, end: m.index },
579
+ right: { start: m.index, end: end },
580
+ wholeMatch: { start: start, end: end },
581
+ }
582
+ pos.push(obj)
583
+ if (!g) {
584
+ return pos
585
+ }
586
+ }
587
+ }
588
+ }
589
+ } while (t && (x.lastIndex = s))
590
+
591
+ return pos
592
+ }
593
+
594
+ /**
595
+ * matchRecursiveRegExp
596
+ *
597
+ * (c) 2007 Steven Levithan <stevenlevithan.com>
598
+ * MIT License
599
+ *
600
+ * Accepts a string to search, a left and right format delimiter
601
+ * as regex patterns, and optional regex flags. Returns an array
602
+ * of matches, allowing nested instances of left/right delimiters.
603
+ * Use the "g" flag to return all matches, otherwise only the
604
+ * first is returned. Be careful to ensure that the left and
605
+ * right format delimiters produce mutually exclusive matches.
606
+ * Backreferences are not supported within the right delimiter
607
+ * due to how it is internally combined with the left delimiter.
608
+ * When matching strings whose format delimiters are unbalanced
609
+ * to the left or right, the output is intentionally as a
610
+ * conventional regex library with recursion support would
611
+ * produce, e.g. "<<x>" and "<x>>" both produce ["x"] when using
612
+ * "<" and ">" as the delimiters (both strings contain a single,
613
+ * balanced instance of "<x>").
614
+ *
615
+ * examples:
616
+ * matchRecursiveRegExp("test", "\\(", "\\)")
617
+ * returns: []
618
+ * matchRecursiveRegExp("<t<<e>><s>>t<>", "<", ">", "g")
619
+ * returns: ["t<<e>><s>", ""]
620
+ * matchRecursiveRegExp("<div id=\"x\">test</div>", "<div\\b[^>]*>", "</div>", "gi")
621
+ * returns: ["test"]
622
+ */
623
+ showdown.helper.matchRecursiveRegExp = function (str, left, right, flags) {
624
+ 'use strict'
625
+
626
+ var matchPos = rgxFindMatchPos(str, left, right, flags),
627
+ results = []
628
+
629
+ for (var i = 0; i < matchPos.length; ++i) {
630
+ results.push([
631
+ str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end),
632
+ str.slice(matchPos[i].match.start, matchPos[i].match.end),
633
+ str.slice(matchPos[i].left.start, matchPos[i].left.end),
634
+ str.slice(matchPos[i].right.start, matchPos[i].right.end),
635
+ ])
636
+ }
637
+ return results
638
+ }
639
+
640
+ /**
641
+ *
642
+ * @param {string} str
643
+ * @param {string|function} replacement
644
+ * @param {string} left
645
+ * @param {string} right
646
+ * @param {string} flags
647
+ * @returns {string}
648
+ */
649
+ showdown.helper.replaceRecursiveRegExp = function (str, replacement, left, right, flags) {
650
+ 'use strict'
651
+
652
+ if (!showdown.helper.isFunction(replacement)) {
653
+ var repStr = replacement
654
+ replacement = function () {
655
+ return repStr
656
+ }
657
+ }
658
+
659
+ var matchPos = rgxFindMatchPos(str, left, right, flags),
660
+ finalStr = str,
661
+ lng = matchPos.length
662
+
663
+ if (lng > 0) {
664
+ var bits = []
665
+ if (matchPos[0].wholeMatch.start !== 0) {
666
+ bits.push(str.slice(0, matchPos[0].wholeMatch.start))
667
+ }
668
+ for (var i = 0; i < lng; ++i) {
669
+ bits.push(
670
+ replacement(
671
+ str.slice(matchPos[i].wholeMatch.start, matchPos[i].wholeMatch.end),
672
+ str.slice(matchPos[i].match.start, matchPos[i].match.end),
673
+ str.slice(matchPos[i].left.start, matchPos[i].left.end),
674
+ str.slice(matchPos[i].right.start, matchPos[i].right.end),
675
+ ),
676
+ )
677
+ if (i < lng - 1) {
678
+ bits.push(str.slice(matchPos[i].wholeMatch.end, matchPos[i + 1].wholeMatch.start))
679
+ }
680
+ }
681
+ if (matchPos[lng - 1].wholeMatch.end < str.length) {
682
+ bits.push(str.slice(matchPos[lng - 1].wholeMatch.end))
683
+ }
684
+ finalStr = bits.join('')
685
+ }
686
+ return finalStr
687
+ }
688
+
689
+ /**
690
+ * POLYFILLS
691
+ */
692
+ if (showdown.helper.isUndefined(console)) {
693
+ console = {
694
+ warn: function (msg) {
695
+ 'use strict'
696
+ alert(msg)
697
+ },
698
+ log: function (msg) {
699
+ 'use strict'
700
+ alert(msg)
701
+ },
702
+ error: function (msg) {
703
+ 'use strict'
704
+ throw msg
705
+ },
706
+ }
707
+ }
708
+
709
+ /**
710
+ * Created by Estevao on 31-05-2015.
711
+ */
712
+
713
+ /**
714
+ * Showdown Converter class
715
+ * @class
716
+ * @param {object} [converterOptions]
717
+ * @returns {Converter}
718
+ */
719
+ showdown.Converter = function (converterOptions) {
720
+ 'use strict'
721
+
722
+ var /**
723
+ * Options used by this converter
724
+ * @private
725
+ * @type {{}}
726
+ */
727
+ options = {},
728
+ /**
729
+ * Language extensions used by this converter
730
+ * @private
731
+ * @type {Array}
732
+ */
733
+ langExtensions = [],
734
+ /**
735
+ * Output modifiers extensions used by this converter
736
+ * @private
737
+ * @type {Array}
738
+ */
739
+ outputModifiers = [],
740
+ /**
741
+ * Event listeners
742
+ * @private
743
+ * @type {{}}
744
+ */
745
+ listeners = {}
746
+
747
+ _constructor()
748
+
749
+ /**
750
+ * Converter constructor
751
+ * @private
752
+ */
753
+ function _constructor() {
754
+ converterOptions = converterOptions || {}
755
+
756
+ for (var gOpt in globalOptions) {
757
+ if (globalOptions.hasOwnProperty(gOpt)) {
758
+ options[gOpt] = globalOptions[gOpt]
759
+ }
760
+ }
761
+
762
+ // Merge options
763
+ if (typeof converterOptions === 'object') {
764
+ for (var opt in converterOptions) {
765
+ if (converterOptions.hasOwnProperty(opt)) {
766
+ options[opt] = converterOptions[opt]
767
+ }
768
+ }
769
+ } else {
770
+ throw Error(
771
+ 'Converter expects the passed parameter to be an object, but ' +
772
+ typeof converterOptions +
773
+ ' was passed instead.',
774
+ )
775
+ }
776
+
777
+ if (options.extensions) {
778
+ showdown.helper.forEach(options.extensions, _parseExtension)
779
+ }
780
+ }
781
+
782
+ /**
783
+ * Parse extension
784
+ * @param {*} ext
785
+ * @param {string} [name='']
786
+ * @private
787
+ */
788
+ function _parseExtension(ext, name) {
789
+ name = name || null
790
+ // If it's a string, the extension was previously loaded
791
+ if (showdown.helper.isString(ext)) {
792
+ ext = showdown.helper.stdExtName(ext)
793
+ name = ext
794
+
795
+ // LEGACY_SUPPORT CODE
796
+ if (showdown.extensions[ext]) {
797
+ console.warn(
798
+ 'DEPRECATION WARNING: ' +
799
+ ext +
800
+ ' is an old extension that uses a deprecated loading method.' +
801
+ 'Please inform the developer that the extension should be updated!',
802
+ )
803
+ legacyExtensionLoading(showdown.extensions[ext], ext)
804
+ return
805
+ // END LEGACY SUPPORT CODE
806
+ } else if (!showdown.helper.isUndefined(extensions[ext])) {
807
+ ext = extensions[ext]
808
+ } else {
809
+ throw Error('Extension "' + ext + '" could not be loaded. It was either not found or is not a valid extension.')
810
+ }
811
+ }
812
+
813
+ if (typeof ext === 'function') {
814
+ ext = ext()
815
+ }
816
+
817
+ if (!showdown.helper.isArray(ext)) {
818
+ ext = [ext]
819
+ }
820
+
821
+ var validExt = validate(ext, name)
822
+ if (!validExt.valid) {
823
+ throw Error(validExt.error)
824
+ }
825
+
826
+ for (var i = 0; i < ext.length; ++i) {
827
+ switch (ext[i].type) {
828
+ case 'lang':
829
+ langExtensions.push(ext[i])
830
+ break
831
+
832
+ case 'output':
833
+ outputModifiers.push(ext[i])
834
+ break
835
+ }
836
+ if (ext[i].hasOwnProperty(listeners)) {
837
+ for (var ln in ext[i].listeners) {
838
+ if (ext[i].listeners.hasOwnProperty(ln)) {
839
+ listen(ln, ext[i].listeners[ln])
840
+ }
841
+ }
842
+ }
843
+ }
844
+ }
845
+
846
+ /**
847
+ * LEGACY_SUPPORT
848
+ * @param {*} ext
849
+ * @param {string} name
850
+ */
851
+ function legacyExtensionLoading(ext, name) {
852
+ if (typeof ext === 'function') {
853
+ ext = ext(new showdown.Converter())
854
+ }
855
+ if (!showdown.helper.isArray(ext)) {
856
+ ext = [ext]
857
+ }
858
+ var valid = validate(ext, name)
859
+
860
+ if (!valid.valid) {
861
+ throw Error(valid.error)
862
+ }
863
+
864
+ for (var i = 0; i < ext.length; ++i) {
865
+ switch (ext[i].type) {
866
+ case 'lang':
867
+ langExtensions.push(ext[i])
868
+ break
869
+ case 'output':
870
+ outputModifiers.push(ext[i])
871
+ break
872
+ default: // should never reach here
873
+ throw Error('Extension loader error: Type unrecognized!!!')
874
+ }
875
+ }
876
+ }
877
+
878
+ /**
879
+ * Listen to an event
880
+ * @param {string} name
881
+ * @param {function} callback
882
+ */
883
+ function listen(name, callback) {
884
+ if (!showdown.helper.isString(name)) {
885
+ throw Error('Invalid argument in converter.listen() method: name must be a string, but ' + typeof name + ' given')
886
+ }
887
+
888
+ if (typeof callback !== 'function') {
889
+ throw Error(
890
+ 'Invalid argument in converter.listen() method: callback must be a function, but ' + typeof callback + ' given',
891
+ )
892
+ }
893
+
894
+ if (!listeners.hasOwnProperty(name)) {
895
+ listeners[name] = []
896
+ }
897
+ listeners[name].push(callback)
898
+ }
899
+
900
+ function rTrimInputText(text) {
901
+ var rsp = text.match(/^\s*/)[0].length,
902
+ rgx = new RegExp('^\\s{0,' + rsp + '}', 'gm')
903
+ return text.replace(rgx, '')
904
+ }
905
+
906
+ /**
907
+ * Dispatch an event
908
+ * @private
909
+ * @param {string} evtName Event name
910
+ * @param {string} text Text
911
+ * @param {{}} options Converter Options
912
+ * @param {{}} globals
913
+ * @returns {string}
914
+ */
915
+ this._dispatch = function dispatch(evtName, text, options, globals) {
916
+ if (listeners.hasOwnProperty(evtName)) {
917
+ for (var ei = 0; ei < listeners[evtName].length; ++ei) {
918
+ var nText = listeners[evtName][ei](evtName, text, this, options, globals)
919
+ if (nText && typeof nText !== 'undefined') {
920
+ text = nText
921
+ }
922
+ }
923
+ }
924
+ return text
925
+ }
926
+
927
+ /**
928
+ * Listen to an event
929
+ * @param {string} name
930
+ * @param {function} callback
931
+ * @returns {showdown.Converter}
932
+ */
933
+ this.listen = function (name, callback) {
934
+ listen(name, callback)
935
+ return this
936
+ }
937
+
938
+ /**
939
+ * Converts a markdown string into HTML
940
+ * @param {string} text
941
+ * @returns {*}
942
+ */
943
+ this.makeHtml = function (text) {
944
+ //check if text is not falsy
945
+ if (!text) {
946
+ return text
947
+ }
948
+
949
+ var globals = {
950
+ gHtmlBlocks: [],
951
+ gHtmlMdBlocks: [],
952
+ gHtmlSpans: [],
953
+ gUrls: {},
954
+ gTitles: {},
955
+ gDimensions: {},
956
+ gListLevel: 0,
957
+ hashLinkCounts: {},
958
+ langExtensions: langExtensions,
959
+ outputModifiers: outputModifiers,
960
+ converter: this,
961
+ ghCodeBlocks: [],
962
+ }
963
+
964
+ // attacklab: Replace ~ with ~T
965
+ // This lets us use tilde as an escape char to avoid md5 hashes
966
+ // The choice of character is arbitrary; anything that isn't
967
+ // magic in Markdown will work.
968
+ text = text.replace(/~/g, '~T')
969
+
970
+ // attacklab: Replace $ with ~D
971
+ // RegExp interprets $ as a special character
972
+ // when it's in a replacement string
973
+ text = text.replace(/\$/g, '~D')
974
+
975
+ // Standardize line endings
976
+ text = text.replace(/\r\n/g, '\n') // DOS to Unix
977
+ text = text.replace(/\r/g, '\n') // Mac to Unix
978
+
979
+ if (options.smartIndentationFix) {
980
+ text = rTrimInputText(text)
981
+ }
982
+
983
+ // Make sure text begins and ends with a couple of newlines:
984
+ //text = '\n\n' + text + '\n\n';
985
+ text = text
986
+ // detab
987
+ text = showdown.subParser('detab')(text, options, globals)
988
+
989
+ // stripBlankLines
990
+ text = showdown.subParser('stripBlankLines')(text, options, globals)
991
+
992
+ //run languageExtensions
993
+ showdown.helper.forEach(langExtensions, function (ext) {
994
+ text = showdown.subParser('runExtension')(ext, text, options, globals)
995
+ })
996
+
997
+ // run the sub parsers
998
+ text = showdown.subParser('hashPreCodeTags')(text, options, globals)
999
+ text = showdown.subParser('githubCodeBlocks')(text, options, globals)
1000
+ text = showdown.subParser('hashHTMLBlocks')(text, options, globals)
1001
+ text = showdown.subParser('hashHTMLSpans')(text, options, globals)
1002
+ text = showdown.subParser('stripLinkDefinitions')(text, options, globals)
1003
+ text = showdown.subParser('blockGamut')(text, options, globals)
1004
+ text = showdown.subParser('unhashHTMLSpans')(text, options, globals)
1005
+ text = showdown.subParser('unescapeSpecialChars')(text, options, globals)
1006
+
1007
+ // attacklab: Restore dollar signs
1008
+ text = text.replace(/~D/g, '$$')
1009
+
1010
+ // attacklab: Restore tildes
1011
+ text = text.replace(/~T/g, '~')
1012
+
1013
+ // Run output modifiers
1014
+ showdown.helper.forEach(outputModifiers, function (ext) {
1015
+ text = showdown.subParser('runExtension')(ext, text, options, globals)
1016
+ })
1017
+ return text
1018
+ }
1019
+
1020
+ /**
1021
+ * Set an option of this Converter instance
1022
+ * @param {string} key
1023
+ * @param {*} value
1024
+ */
1025
+ this.setOption = function (key, value) {
1026
+ options[key] = value
1027
+ }
1028
+
1029
+ /**
1030
+ * Get the option of this Converter instance
1031
+ * @param {string} key
1032
+ * @returns {*}
1033
+ */
1034
+ this.getOption = function (key) {
1035
+ return options[key]
1036
+ }
1037
+
1038
+ /**
1039
+ * Get the options of this Converter instance
1040
+ * @returns {{}}
1041
+ */
1042
+ this.getOptions = function () {
1043
+ return options
1044
+ }
1045
+
1046
+ /**
1047
+ * Add extension to THIS converter
1048
+ * @param {{}} extension
1049
+ * @param {string} [name=null]
1050
+ */
1051
+ this.addExtension = function (extension, name) {
1052
+ name = name || null
1053
+ _parseExtension(extension, name)
1054
+ }
1055
+
1056
+ /**
1057
+ * Use a global registered extension with THIS converter
1058
+ * @param {string} extensionName Name of the previously registered extension
1059
+ */
1060
+ this.useExtension = function (extensionName) {
1061
+ _parseExtension(extensionName)
1062
+ }
1063
+
1064
+ /**
1065
+ * Set the flavor THIS converter should use
1066
+ * @param {string} name
1067
+ */
1068
+ this.setFlavor = function (name) {
1069
+ if (flavor.hasOwnProperty(name)) {
1070
+ var preset = flavor[name]
1071
+ for (var option in preset) {
1072
+ if (preset.hasOwnProperty(option)) {
1073
+ options[option] = preset[option]
1074
+ }
1075
+ }
1076
+ }
1077
+ }
1078
+
1079
+ /**
1080
+ * Remove an extension from THIS converter.
1081
+ * Note: This is a costly operation. It's better to initialize a new converter
1082
+ * and specify the extensions you wish to use
1083
+ * @param {Array} extension
1084
+ */
1085
+ this.removeExtension = function (extension) {
1086
+ if (!showdown.helper.isArray(extension)) {
1087
+ extension = [extension]
1088
+ }
1089
+ for (var a = 0; a < extension.length; ++a) {
1090
+ var ext = extension[a]
1091
+ for (var i = 0; i < langExtensions.length; ++i) {
1092
+ if (langExtensions[i] === ext) {
1093
+ langExtensions[i].splice(i, 1)
1094
+ }
1095
+ }
1096
+ for (var ii = 0; ii < outputModifiers.length; ++i) {
1097
+ if (outputModifiers[ii] === ext) {
1098
+ outputModifiers[ii].splice(i, 1)
1099
+ }
1100
+ }
1101
+ }
1102
+ }
1103
+
1104
+ /**
1105
+ * Get all extension of THIS converter
1106
+ * @returns {{language: Array, output: Array}}
1107
+ */
1108
+ this.getAllExtensions = function () {
1109
+ return {
1110
+ language: langExtensions,
1111
+ output: outputModifiers,
1112
+ }
1113
+ }
1114
+ }
1115
+
1116
+ /**
1117
+ * Turn Markdown link shortcuts into XHTML <a> tags.
1118
+ */
1119
+ showdown.subParser('anchors', function (text, options, globals) {
1120
+ 'use strict'
1121
+
1122
+ text = globals.converter._dispatch('anchors.before', text, options, globals)
1123
+
1124
+ var writeAnchorTag = function (wholeMatch, m1, m2, m3, m4, m5, m6, m7) {
1125
+ if (showdown.helper.isUndefined(m7)) {
1126
+ m7 = ''
1127
+ }
1128
+ wholeMatch = m1
1129
+ var linkText = m2,
1130
+ linkId = m3.toLowerCase(),
1131
+ url = m4,
1132
+ title = m7
1133
+
1134
+ if (!url) {
1135
+ if (!linkId) {
1136
+ // lower-case and turn embedded newlines into spaces
1137
+ linkId = linkText.toLowerCase().replace(/ ?\n/g, ' ')
1138
+ }
1139
+ url = '#' + linkId
1140
+
1141
+ if (!showdown.helper.isUndefined(globals.gUrls[linkId])) {
1142
+ url = globals.gUrls[linkId]
1143
+ if (!showdown.helper.isUndefined(globals.gTitles[linkId])) {
1144
+ title = globals.gTitles[linkId]
1145
+ }
1146
+ } else {
1147
+ if (wholeMatch.search(/\(\s*\)$/m) > -1) {
1148
+ // Special case for explicit empty url
1149
+ url = ''
1150
+ } else {
1151
+ return wholeMatch
1152
+ }
1153
+ }
1154
+ }
1155
+
1156
+ url = showdown.helper.escapeCharacters(url, '*_', false)
1157
+ var result = '<a href="' + url + '"'
1158
+
1159
+ if (title !== '' && title !== null) {
1160
+ title = title.replace(/"/g, '&quot;')
1161
+ title = showdown.helper.escapeCharacters(title, '*_', false)
1162
+ result += ' title="' + title + '"'
1163
+ }
1164
+
1165
+ result += '>' + linkText + '</a>'
1166
+
1167
+ return result
1168
+ }
1169
+ text = text.replace(/(\[((?:\[[^\]]*]|[^\[\]])*)][ ]?(?:\n[ ]*)?\[(.*?)])()()()()/g, writeAnchorTag)
1170
+ text = text.replace(
1171
+ /(\[((?:\[[^\]]*]|[^\[\]])*)]\([ \t]*()<?(.*?(?:\(.*?\).*?)?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g,
1172
+ writeAnchorTag,
1173
+ )
1174
+ text = text.replace(/(\[([^\[\]]+)])()()()()()/g, writeAnchorTag)
1175
+
1176
+ text = globals.converter._dispatch('anchors.after', text, options, globals)
1177
+ return text
1178
+ })
1179
+
1180
+ showdown.subParser('autoLinks', function (text, options, globals) {
1181
+ 'use strict'
1182
+
1183
+ text = globals.converter._dispatch('autoLinks.before', text, options, globals)
1184
+
1185
+ var simpleURLRegex = /\b(((https?|ftp|dict):\/\/|www\.)[^'">\s]+\.[^'">\s]+)(?=\s|$)(?!["<>])/gi,
1186
+ delimUrlRegex = /<(((https?|ftp|dict):\/\/|www\.)[^'">\s]+)>/gi,
1187
+ simpleMailRegex =
1188
+ /(?:^|[ \n\t])([A-Za-z0-9!#$%&'*+-/=?^_`\{|}~\.]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)(?:$|[ \n\t])/gi,
1189
+ delimMailRegex = /<(?:mailto:)?([-.\w]+@[-a-z0-9]+(\.[-a-z0-9]+)*\.[a-z]+)>/gi
1190
+
1191
+ text = text.replace(delimUrlRegex, replaceLink)
1192
+ text = text.replace(delimMailRegex, replaceMail)
1193
+ // simpleURLRegex = /\b(((https?|ftp|dict):\/\/|www\.)[-.+~:?#@!$&'()*,;=[\]\w]+)\b/gi,
1194
+ // Email addresses: <address@domain.foo>
1195
+
1196
+ if (options.simplifiedAutoLink) {
1197
+ text = text.replace(simpleURLRegex, replaceLink)
1198
+ text = text.replace(simpleMailRegex, replaceMail)
1199
+ }
1200
+
1201
+ function replaceLink(wm, link) {
1202
+ var lnkTxt = link
1203
+ if (/^www\./i.test(link)) {
1204
+ link = link.replace(/^www\./i, 'http://www.')
1205
+ }
1206
+ return '<a href="' + link + '">' + lnkTxt + '</a>'
1207
+ }
1208
+
1209
+ function replaceMail(wholeMatch, m1) {
1210
+ var unescapedStr = showdown.subParser('unescapeSpecialChars')(m1)
1211
+ return showdown.subParser('encodeEmailAddress')(unescapedStr)
1212
+ }
1213
+
1214
+ text = globals.converter._dispatch('autoLinks.after', text, options, globals)
1215
+
1216
+ return text
1217
+ })
1218
+
1219
+ /**
1220
+ * These are all the transformations that form block-level
1221
+ * tags like paragraphs, headers, and list items.
1222
+ */
1223
+ showdown.subParser('blockGamut', function (text, options, globals) {
1224
+ 'use strict'
1225
+
1226
+ text = globals.converter._dispatch('blockGamut.before', text, options, globals)
1227
+
1228
+ // we parse blockquotes first so that we can have headings and hrs
1229
+ // inside blockquotes
1230
+ text = showdown.subParser('blockQuotes')(text, options, globals)
1231
+ text = showdown.subParser('headers')(text, options, globals)
1232
+
1233
+ // Do Horizontal Rules:
1234
+ var key = showdown.subParser('hashBlock')('<hr />', options, globals)
1235
+ text = text.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm, key)
1236
+ text = text.replace(/^[ ]{0,2}([ ]?\-[ ]?){3,}[ \t]*$/gm, key)
1237
+ text = text.replace(/^[ ]{0,2}([ ]?_[ ]?){3,}[ \t]*$/gm, key)
1238
+
1239
+ text = showdown.subParser('lists')(text, options, globals)
1240
+ text = showdown.subParser('codeBlocks')(text, options, globals)
1241
+ text = showdown.subParser('tables')(text, options, globals)
1242
+
1243
+ // We already ran _HashHTMLBlocks() before, in Markdown(), but that
1244
+ // was to escape raw HTML in the original Markdown source. This time,
1245
+ // we're escaping the markup we've just created, so that we don't wrap
1246
+ // <p> tags around block-level tags.
1247
+ text = showdown.subParser('hashHTMLBlocks')(text, options, globals)
1248
+ text = showdown.subParser('paragraphs')(text, options, globals)
1249
+
1250
+ text = globals.converter._dispatch('blockGamut.after', text, options, globals)
1251
+
1252
+ return text
1253
+ })
1254
+
1255
+ showdown.subParser('blockQuotes', function (text, options, globals) {
1256
+ 'use strict'
1257
+
1258
+ text = globals.converter._dispatch('blockQuotes.before', text, options, globals)
1259
+
1260
+ text = text.replace(/((^[ \t]{0,3}>[ \t]?.+\n(.+\n)*\n*)+)/gm, function (wholeMatch, m1) {
1261
+ var bq = m1
1262
+
1263
+ // attacklab: hack around Konqueror 3.5.4 bug:
1264
+ // "----------bug".replace(/^-/g,"") == "bug"
1265
+ bq = bq.replace(/^[ \t]*>[ \t]?/gm, '~0') // trim one level of quoting
1266
+
1267
+ // attacklab: clean up hack
1268
+ bq = bq.replace(/~0/g, '')
1269
+
1270
+ bq = bq.replace(/^[ \t]+$/gm, '') // trim whitespace-only lines
1271
+ bq = showdown.subParser('githubCodeBlocks')(bq, options, globals)
1272
+ bq = showdown.subParser('blockGamut')(bq, options, globals) // recurse
1273
+
1274
+ bq = bq.replace(/(^|\n)/g, '$1 ')
1275
+ // These leading spaces screw with <pre> content, so we need to fix that:
1276
+ bq = bq.replace(/(\s*<pre>[^\r]+?<\/pre>)/gm, function (wholeMatch, m1) {
1277
+ var pre = m1
1278
+ // attacklab: hack around Konqueror 3.5.4 bug:
1279
+ pre = pre.replace(/^ /gm, '~0')
1280
+ pre = pre.replace(/~0/g, '')
1281
+ return pre
1282
+ })
1283
+
1284
+ return showdown.subParser('hashBlock')('<blockquote>\n' + bq + '\n</blockquote>', options, globals)
1285
+ })
1286
+
1287
+ text = globals.converter._dispatch('blockQuotes.after', text, options, globals)
1288
+ return text
1289
+ })
1290
+
1291
+ /**
1292
+ * Process Markdown `<pre><code>` blocks.
1293
+ */
1294
+ showdown.subParser('codeBlocks', function (text, options, globals) {
1295
+ 'use strict'
1296
+
1297
+ text = globals.converter._dispatch('codeBlocks.before', text, options, globals)
1298
+ text += '~0'
1299
+
1300
+ var pattern = /(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g
1301
+ text = text.replace(pattern, function (wholeMatch, m1, m2) {
1302
+ var codeblock = m1,
1303
+ nextChar = m2,
1304
+ end = '\n'
1305
+
1306
+ codeblock = showdown.subParser('outdent')(codeblock)
1307
+ codeblock = showdown.subParser('encodeCode')(codeblock)
1308
+ codeblock = showdown.subParser('detab')(codeblock)
1309
+ codeblock = codeblock.replace(/^\n+/g, '') // trim leading newlines
1310
+ codeblock = codeblock.replace(/\n+$/g, '') // trim trailing newlines
1311
+
1312
+ if (options.omitExtraWLInCodeBlocks) {
1313
+ end = ''
1314
+ }
1315
+
1316
+ codeblock = '<pre><code>' + codeblock + end + '</code></pre>'
1317
+
1318
+ return showdown.subParser('hashBlock')(codeblock, options, globals) + nextChar
1319
+ })
1320
+
1321
+ text = text.replace(/~0/, '')
1322
+
1323
+ text = globals.converter._dispatch('codeBlocks.after', text, options, globals)
1324
+ return text
1325
+ })
1326
+ showdown.subParser('codeSpans', function (text, options, globals) {
1327
+ 'use strict'
1328
+
1329
+ text = globals.converter._dispatch('codeSpans.before', text, options, globals)
1330
+
1331
+ if (typeof text === 'undefined') {
1332
+ text = ''
1333
+ }
1334
+ text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm, function (wholeMatch, m1, m2, m3) {
1335
+ var c = m3
1336
+ c = c.replace(/^([ \t]*)/g, '') // leading whitespace
1337
+ c = c.replace(/[ \t]*$/g, '') // trailing whitespace
1338
+ c = showdown.subParser('encodeCode')(c)
1339
+ return m1 + '<code>' + c + '</code>'
1340
+ })
1341
+
1342
+ text = globals.converter._dispatch('codeSpans.after', text, options, globals)
1343
+ return text
1344
+ })
1345
+
1346
+ /**
1347
+ * Convert all tabs to spaces
1348
+ */
1349
+ showdown.subParser('detab', function (text) {
1350
+ 'use strict'
1351
+
1352
+ // expand first n-1 tabs
1353
+ text = text.replace(/\t(?=\t)/g, ' ') // g_tab_width
1354
+
1355
+ // replace the nth with two sentinels
1356
+ text = text.replace(/\t/g, '~A~B')
1357
+
1358
+ // use the sentinel to anchor our regex so it doesn't explode
1359
+ text = text.replace(/~B(.+?)~A/g, function (wholeMatch, m1) {
1360
+ var leadingText = m1,
1361
+ numSpaces = 4 - (leadingText.length % 4) // g_tab_width
1362
+
1363
+ // there *must* be a better way to do this:
1364
+ for (var i = 0; i < numSpaces; i++) {
1365
+ leadingText += ' '
1366
+ }
1367
+
1368
+ return leadingText
1369
+ })
1370
+
1371
+ // clean up sentinels
1372
+ text = text.replace(/~A/g, ' ') // g_tab_width
1373
+ text = text.replace(/~B/g, '')
1374
+
1375
+ return text
1376
+ })
1377
+
1378
+ /**
1379
+ * Smart processing for ampersands and angle brackets that need to be encoded.
1380
+ */
1381
+ showdown.subParser('encodeAmpsAndAngles', function (text) {
1382
+ 'use strict'
1383
+ // Ampersand-encoding based entirely on Nat Irons's Amputator MT plugin:
1384
+ // http://bumppo.net/projects/amputator/
1385
+ text = text.replace(/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/g, '&amp;')
1386
+
1387
+ // Encode naked <'s
1388
+ text = text.replace(/<(?![a-z\/?\$!])/gi, '&lt;')
1389
+
1390
+ return text
1391
+ })
1392
+
1393
+ /**
1394
+ * Returns the string, with after processing the following backslash escape sequences.
1395
+ *
1396
+ * attacklab: The polite way to do this is with the new escapeCharacters() function:
1397
+ *
1398
+ * text = escapeCharacters(text,"\\",true);
1399
+ * text = escapeCharacters(text,"`*_{}[]()>#+-.!",true);
1400
+ *
1401
+ * ...but we're sidestepping its use of the (slow) RegExp constructor
1402
+ * as an optimization for Firefox. This function gets called a LOT.
1403
+ */
1404
+ showdown.subParser('encodeBackslashEscapes', function (text) {
1405
+ 'use strict'
1406
+ text = text.replace(/\\(\\)/g, showdown.helper.escapeCharactersCallback)
1407
+ text = text.replace(/\\([`*_{}\[\]()>#+-.!])/g, showdown.helper.escapeCharactersCallback)
1408
+ return text
1409
+ })
1410
+
1411
+ /**
1412
+ * Encode/escape certain characters inside Markdown code runs.
1413
+ * The point is that in code, these characters are literals,
1414
+ * and lose their special Markdown meanings.
1415
+ */
1416
+ showdown.subParser('encodeCode', function (text) {
1417
+ 'use strict'
1418
+
1419
+ // Encode all ampersands; HTML entities are not
1420
+ // entities within a Markdown code span.
1421
+ text = text.replace(/&/g, '&amp;')
1422
+
1423
+ // Do the angle bracket song and dance:
1424
+ text = text.replace(/</g, '&lt;')
1425
+ text = text.replace(/>/g, '&gt;')
1426
+
1427
+ // Now, escape characters that are magic in Markdown:
1428
+ text = showdown.helper.escapeCharacters(text, '*_{}[]\\', false)
1429
+
1430
+ // jj the line above breaks this:
1431
+ //---
1432
+ //* Item
1433
+ // 1. Subitem
1434
+ // special char: *
1435
+ // ---
1436
+
1437
+ return text
1438
+ })
1439
+
1440
+ /**
1441
+ * Input: an email address, e.g. "foo@example.com"
1442
+ *
1443
+ * Output: the email address as a mailto link, with each character
1444
+ * of the address encoded as either a decimal or hex entity, in
1445
+ * the hopes of foiling most address harvesting spam bots. E.g.:
1446
+ *
1447
+ * <a href="&#x6D;&#97;&#105;&#108;&#x74;&#111;:&#102;&#111;&#111;&#64;&#101;
1448
+ * x&#x61;&#109;&#x70;&#108;&#x65;&#x2E;&#99;&#111;&#109;">&#102;&#111;&#111;
1449
+ * &#64;&#101;x&#x61;&#109;&#x70;&#108;&#x65;&#x2E;&#99;&#111;&#109;</a>
1450
+ *
1451
+ * Based on a filter by Matthew Wickline, posted to the BBEdit-Talk
1452
+ * mailing list: <http://tinyurl.com/yu7ue>
1453
+ *
1454
+ */
1455
+ showdown.subParser('encodeEmailAddress', function (addr) {
1456
+ 'use strict'
1457
+
1458
+ var encode = [
1459
+ function (ch) {
1460
+ return '&#' + ch.charCodeAt(0) + ';'
1461
+ },
1462
+ function (ch) {
1463
+ return '&#x' + ch.charCodeAt(0).toString(16) + ';'
1464
+ },
1465
+ function (ch) {
1466
+ return ch
1467
+ },
1468
+ ]
1469
+
1470
+ addr = 'mailto:' + addr
1471
+
1472
+ addr = addr.replace(/./g, function (ch) {
1473
+ if (ch === '@') {
1474
+ // this *must* be encoded. I insist.
1475
+ ch = encode[Math.floor(Math.random() * 2)](ch)
1476
+ } else if (ch !== ':') {
1477
+ // leave ':' alone (to spot mailto: later)
1478
+ var r = Math.random()
1479
+ // roughly 10% raw, 45% hex, 45% dec
1480
+ ch = r > 0.9 ? encode[2](ch) : r > 0.45 ? encode[1](ch) : encode[0](ch)
1481
+ }
1482
+ return ch
1483
+ })
1484
+
1485
+ addr = '<a href="' + addr + '">' + addr + '</a>'
1486
+ addr = addr.replace(/">.+:/g, '">') // strip the mailto: from the visible part
1487
+
1488
+ return addr
1489
+ })
1490
+
1491
+ /**
1492
+ * Within tags -- meaning between < and > -- encode [\ ` * _] so they
1493
+ * don't conflict with their use in Markdown for code, italics and strong.
1494
+ */
1495
+ showdown.subParser('escapeSpecialCharsWithinTagAttributes', function (text) {
1496
+ 'use strict'
1497
+
1498
+ // Build a regex to find HTML tags and comments. See Friedl's
1499
+ // "Mastering Regular Expressions", 2nd Ed., pp. 200-201.
1500
+ var regex = /(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|<!(--.*?--\s*)+>)/gi
1501
+
1502
+ text = text.replace(regex, function (wholeMatch) {
1503
+ var tag = wholeMatch.replace(/(.)<\/?code>(?=.)/g, '$1`')
1504
+ tag = showdown.helper.escapeCharacters(tag, '\\`*_', false)
1505
+ return tag
1506
+ })
1507
+
1508
+ return text
1509
+ })
1510
+
1511
+ /**
1512
+ * Handle github codeblocks prior to running HashHTML so that
1513
+ * HTML contained within the codeblock gets escaped properly
1514
+ * Example:
1515
+ * ```ruby
1516
+ * def hello_world(x)
1517
+ * puts "Hello, #{x}"
1518
+ * end
1519
+ * ```
1520
+ */
1521
+ showdown.subParser('githubCodeBlocks', function (text, options, globals) {
1522
+ 'use strict'
1523
+
1524
+ // early exit if option is not enabled
1525
+ if (!options.ghCodeBlocks) {
1526
+ return text
1527
+ }
1528
+
1529
+ text = globals.converter._dispatch('githubCodeBlocks.before', text, options, globals)
1530
+
1531
+ text += '~0'
1532
+
1533
+ text = text.replace(/(?:^|\n)```(.*)\n([\s\S]*?)\n```/g, function (wholeMatch, language, codeblock) {
1534
+ var end = options.omitExtraWLInCodeBlocks ? '' : '\n'
1535
+
1536
+ // First parse the github code block
1537
+ codeblock = showdown.subParser('encodeCode')(codeblock)
1538
+ codeblock = showdown.subParser('detab')(codeblock)
1539
+ codeblock = codeblock.replace(/^\n+/g, '') // trim leading newlines
1540
+ codeblock = codeblock.replace(/\n+$/g, '') // trim trailing whitespace
1541
+
1542
+ codeblock =
1543
+ '<pre><code' +
1544
+ (language ? ' class="' + language + ' language-' + language + '"' : '') +
1545
+ '>' +
1546
+ codeblock +
1547
+ end +
1548
+ '</code></pre>'
1549
+
1550
+ codeblock = showdown.subParser('hashBlock')(codeblock, options, globals)
1551
+
1552
+ // Since GHCodeblocks can be false positives, we need to
1553
+ // store the primitive text and the parsed text in a global var,
1554
+ // and then return a token
1555
+ return '\n\n~G' + (globals.ghCodeBlocks.push({ text: wholeMatch, codeblock: codeblock }) - 1) + 'G\n\n'
1556
+ })
1557
+
1558
+ // attacklab: strip sentinel
1559
+ text = text.replace(/~0/, '')
1560
+
1561
+ return globals.converter._dispatch('githubCodeBlocks.after', text, options, globals)
1562
+ })
1563
+
1564
+ showdown.subParser('hashBlock', function (text, options, globals) {
1565
+ 'use strict'
1566
+ text = text.replace(/(^\n+|\n+$)/g, '')
1567
+ return '\n\n~K' + (globals.gHtmlBlocks.push(text) - 1) + 'K\n\n'
1568
+ })
1569
+
1570
+ showdown.subParser('hashElement', function (text, options, globals) {
1571
+ 'use strict'
1572
+
1573
+ return function (wholeMatch, m1) {
1574
+ var blockText = m1
1575
+
1576
+ // Undo double lines
1577
+ blockText = blockText.replace(/\n\n/g, '\n')
1578
+ blockText = blockText.replace(/^\n/, '')
1579
+
1580
+ // strip trailing blank lines
1581
+ blockText = blockText.replace(/\n+$/g, '')
1582
+
1583
+ // Replace the element text with a marker ("~KxK" where x is its key)
1584
+ blockText = '\n\n~K' + (globals.gHtmlBlocks.push(blockText) - 1) + 'K\n\n'
1585
+
1586
+ return blockText
1587
+ }
1588
+ })
1589
+
1590
+ showdown.subParser('hashHTMLBlocks', function (text, options, globals) {
1591
+ 'use strict'
1592
+
1593
+ var blockTags = [
1594
+ 'pre',
1595
+ 'div',
1596
+ 'h1',
1597
+ 'h2',
1598
+ 'h3',
1599
+ 'h4',
1600
+ 'h5',
1601
+ 'h6',
1602
+ 'blockquote',
1603
+ 'table',
1604
+ 'dl',
1605
+ 'ol',
1606
+ 'ul',
1607
+ 'script',
1608
+ 'noscript',
1609
+ 'form',
1610
+ 'fieldset',
1611
+ 'iframe',
1612
+ 'math',
1613
+ 'style',
1614
+ 'section',
1615
+ 'header',
1616
+ 'footer',
1617
+ 'nav',
1618
+ 'article',
1619
+ 'aside',
1620
+ 'address',
1621
+ 'audio',
1622
+ 'canvas',
1623
+ 'figure',
1624
+ 'hgroup',
1625
+ 'output',
1626
+ 'video',
1627
+ 'p',
1628
+ ],
1629
+ repFunc = function (wholeMatch, match, left, right) {
1630
+ var txt = wholeMatch
1631
+ // check if this html element is marked as markdown
1632
+ // if so, it's contents should be parsed as markdown
1633
+ if (left.search(/\bmarkdown\b/) !== -1) {
1634
+ txt = left + globals.converter.makeHtml(match) + right
1635
+ }
1636
+ return '\n\n~K' + (globals.gHtmlBlocks.push(txt) - 1) + 'K\n\n'
1637
+ }
1638
+
1639
+ for (var i = 0; i < blockTags.length; ++i) {
1640
+ text = showdown.helper.replaceRecursiveRegExp(
1641
+ text,
1642
+ repFunc,
1643
+ '^(?: |\\t){0,3}<' + blockTags[i] + '\\b[^>]*>',
1644
+ '</' + blockTags[i] + '>',
1645
+ 'gim',
1646
+ )
1647
+ }
1648
+
1649
+ // HR SPECIAL CASE
1650
+ text = text.replace(
1651
+ /(\n[ ]{0,3}(<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g,
1652
+ showdown.subParser('hashElement')(text, options, globals),
1653
+ )
1654
+
1655
+ // Special case for standalone HTML comments:
1656
+ text = text.replace(/(<!--[\s\S]*?-->)/g, showdown.subParser('hashElement')(text, options, globals))
1657
+
1658
+ // PHP and ASP-style processor instructions (<?...?> and <%...%>)
1659
+ text = text.replace(
1660
+ /(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g,
1661
+ showdown.subParser('hashElement')(text, options, globals),
1662
+ )
1663
+ return text
1664
+ })
1665
+
1666
+ /**
1667
+ * Hash span elements that should not be parsed as markdown
1668
+ */
1669
+ showdown.subParser('hashHTMLSpans', function (text, config, globals) {
1670
+ 'use strict'
1671
+
1672
+ var matches = showdown.helper.matchRecursiveRegExp(text, '<code\\b[^>]*>', '</code>', 'gi')
1673
+
1674
+ for (var i = 0; i < matches.length; ++i) {
1675
+ text = text.replace(matches[i][0], '~L' + (globals.gHtmlSpans.push(matches[i][0]) - 1) + 'L')
1676
+ }
1677
+ return text
1678
+ })
1679
+
1680
+ /**
1681
+ * Unhash HTML spans
1682
+ */
1683
+ showdown.subParser('unhashHTMLSpans', function (text, config, globals) {
1684
+ 'use strict'
1685
+
1686
+ for (var i = 0; i < globals.gHtmlSpans.length; ++i) {
1687
+ text = text.replace('~L' + i + 'L', globals.gHtmlSpans[i])
1688
+ }
1689
+
1690
+ return text
1691
+ })
1692
+
1693
+ /**
1694
+ * Hash span elements that should not be parsed as markdown
1695
+ */
1696
+ showdown.subParser('hashPreCodeTags', function (text, config, globals) {
1697
+ 'use strict'
1698
+
1699
+ var repFunc = function (wholeMatch, match, left, right) {
1700
+ // encode html entities
1701
+ var codeblock = left + showdown.subParser('encodeCode')(match) + right
1702
+ return '\n\n~G' + (globals.ghCodeBlocks.push({ text: wholeMatch, codeblock: codeblock }) - 1) + 'G\n\n'
1703
+ }
1704
+
1705
+ text = showdown.helper.replaceRecursiveRegExp(
1706
+ text,
1707
+ repFunc,
1708
+ '^(?: |\\t){0,3}<pre\\b[^>]*>\\s*<code\\b[^>]*>',
1709
+ '^(?: |\\t){0,3}</code>\\s*</pre>',
1710
+ 'gim',
1711
+ )
1712
+ return text
1713
+ })
1714
+
1715
+ showdown.subParser('headers', function (text, options, globals) {
1716
+ 'use strict'
1717
+
1718
+ text = globals.converter._dispatch('headers.before', text, options, globals)
1719
+
1720
+ var prefixHeader = options.prefixHeaderId,
1721
+ headerLevelStart = isNaN(parseInt(options.headerLevelStart)) ? 1 : parseInt(options.headerLevelStart),
1722
+ // Set text-style headers:
1723
+ // Header 1
1724
+ // ========
1725
+ //
1726
+ // Header 2
1727
+ // --------
1728
+ //
1729
+ setextRegexH1 = options.smoothLivePreview ? /^(.+)[ \t]*\n={2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n=+[ \t]*\n+/gm,
1730
+ setextRegexH2 = options.smoothLivePreview ? /^(.+)[ \t]*\n-{2,}[ \t]*\n+/gm : /^(.+)[ \t]*\n-+[ \t]*\n+/gm
1731
+
1732
+ text = text.replace(setextRegexH1, function (wholeMatch, m1) {
1733
+ var spanGamut = showdown.subParser('spanGamut')(m1, options, globals),
1734
+ hID = options.noHeaderId ? '' : ' id="' + headerId(m1) + '"',
1735
+ hLevel = headerLevelStart,
1736
+ hashBlock = '<h' + hLevel + hID + '>' + spanGamut + '</h' + hLevel + '>'
1737
+ return showdown.subParser('hashBlock')(hashBlock, options, globals)
1738
+ })
1739
+
1740
+ text = text.replace(setextRegexH2, function (matchFound, m1) {
1741
+ var spanGamut = showdown.subParser('spanGamut')(m1, options, globals),
1742
+ hID = options.noHeaderId ? '' : ' id="' + headerId(m1) + '"',
1743
+ hLevel = headerLevelStart + 1,
1744
+ hashBlock = '<h' + hLevel + hID + '>' + spanGamut + '</h' + hLevel + '>'
1745
+ return showdown.subParser('hashBlock')(hashBlock, options, globals)
1746
+ })
1747
+
1748
+ // atx-style headers:
1749
+ // # Header 1
1750
+ // ## Header 2
1751
+ // ## Header 2 with closing hashes ##
1752
+ // ...
1753
+ // ###### Header 6
1754
+ //
1755
+ text = text.replace(/^(#{1,6})[ \t]*(.+?)[ \t]*#*\n+/gm, function (wholeMatch, m1, m2) {
1756
+ var span = showdown.subParser('spanGamut')(m2, options, globals),
1757
+ hID = options.noHeaderId ? '' : ' id="' + headerId(m2) + '"',
1758
+ hLevel = headerLevelStart - 1 + m1.length,
1759
+ header = '<h' + hLevel + hID + '>' + span + '</h' + hLevel + '>'
1760
+
1761
+ return showdown.subParser('hashBlock')(header, options, globals)
1762
+ })
1763
+
1764
+ function headerId(m) {
1765
+ var title,
1766
+ escapedId = m.replace(/[^\w]/g, '').toLowerCase()
1767
+
1768
+ if (globals.hashLinkCounts[escapedId]) {
1769
+ title = escapedId + '-' + globals.hashLinkCounts[escapedId]++
1770
+ } else {
1771
+ title = escapedId
1772
+ globals.hashLinkCounts[escapedId] = 1
1773
+ }
1774
+
1775
+ // Prefix id to prevent causing inadvertent pre-existing style matches.
1776
+ if (prefixHeader === true) {
1777
+ prefixHeader = 'section'
1778
+ }
1779
+
1780
+ if (showdown.helper.isString(prefixHeader)) {
1781
+ return prefixHeader + title
1782
+ }
1783
+ return title
1784
+ }
1785
+
1786
+ text = globals.converter._dispatch('headers.after', text, options, globals)
1787
+ return text
1788
+ })
1789
+
1790
+ /**
1791
+ * Turn Markdown image shortcuts into <img> tags.
1792
+ */
1793
+ showdown.subParser('images', function (text, options, globals) {
1794
+ 'use strict'
1795
+
1796
+ text = globals.converter._dispatch('images.before', text, options, globals)
1797
+
1798
+ var inlineRegExp =
1799
+ /!\[(.*?)]\s?\([ \t]*()<?(\S+?)>?(?: =([*\d]+[A-Za-z%]{0,4})x([*\d]+[A-Za-z%]{0,4}))?[ \t]*(?:(['"])(.*?)\6[ \t]*)?\)/g,
1800
+ referenceRegExp = /!\[([^\]]*?)] ?(?:\n *)?\[(.*?)]()()()()()/g
1801
+
1802
+ function writeImageTag(wholeMatch, altText, linkId, url, width, height, m5, title) {
1803
+ var gUrls = globals.gUrls,
1804
+ gTitles = globals.gTitles,
1805
+ gDims = globals.gDimensions
1806
+
1807
+ linkId = linkId.toLowerCase()
1808
+
1809
+ if (!title) {
1810
+ title = ''
1811
+ }
1812
+
1813
+ if (url === '' || url === null) {
1814
+ if (linkId === '' || linkId === null) {
1815
+ // lower-case and turn embedded newlines into spaces
1816
+ linkId = altText.toLowerCase().replace(/ ?\n/g, ' ')
1817
+ }
1818
+ url = '#' + linkId
1819
+
1820
+ if (!showdown.helper.isUndefined(gUrls[linkId])) {
1821
+ url = gUrls[linkId]
1822
+ if (!showdown.helper.isUndefined(gTitles[linkId])) {
1823
+ title = gTitles[linkId]
1824
+ }
1825
+ if (!showdown.helper.isUndefined(gDims[linkId])) {
1826
+ width = gDims[linkId].width
1827
+ height = gDims[linkId].height
1828
+ }
1829
+ } else {
1830
+ return wholeMatch
1831
+ }
1832
+ }
1833
+
1834
+ altText = altText.replace(/"/g, '&quot;')
1835
+ altText = showdown.helper.escapeCharacters(altText, '*_', false)
1836
+ url = showdown.helper.escapeCharacters(url, '*_', false)
1837
+ var result = '<img src="' + url + '" alt="' + altText + '"'
1838
+
1839
+ if (title) {
1840
+ title = title.replace(/"/g, '&quot;')
1841
+ title = showdown.helper.escapeCharacters(title, '*_', false)
1842
+ result += ' title="' + title + '"'
1843
+ }
1844
+
1845
+ if (width && height) {
1846
+ width = width === '*' ? 'auto' : width
1847
+ height = height === '*' ? 'auto' : height
1848
+
1849
+ result += ' width="' + width + '"'
1850
+ result += ' height="' + height + '"'
1851
+ }
1852
+
1853
+ result += ' />'
1854
+ return result
1855
+ }
1856
+
1857
+ // First, handle reference-style labeled images: ![alt text][id]
1858
+ text = text.replace(referenceRegExp, writeImageTag)
1859
+
1860
+ // Next, handle inline images: ![alt text](url =<width>x<height> "optional title")
1861
+ text = text.replace(inlineRegExp, writeImageTag)
1862
+
1863
+ text = globals.converter._dispatch('images.after', text, options, globals)
1864
+ return text
1865
+ })
1866
+
1867
+ showdown.subParser('italicsAndBold', function (text, options, globals) {
1868
+ 'use strict'
1869
+
1870
+ text = globals.converter._dispatch('italicsAndBold.before', text, options, globals)
1871
+
1872
+ if (options.literalMidWordUnderscores) {
1873
+ //underscores
1874
+ // Since we are consuming a \s character, we need to add it
1875
+ text = text.replace(/(^|\s|>|\b)__(?=\S)([\s\S]+?)__(?=\b|<|\s|$)/gm, '$1<strong>$2</strong>')
1876
+ text = text.replace(/(^|\s|>|\b)_(?=\S)([\s\S]+?)_(?=\b|<|\s|$)/gm, '$1<em>$2</em>')
1877
+ //asterisks
1878
+ text = text.replace(/(\*\*)(?=\S)([^\r]*?\S[*]*)\1/g, '<strong>$2</strong>')
1879
+ text = text.replace(/(\*)(?=\S)([^\r]*?\S)\1/g, '<em>$2</em>')
1880
+ } else {
1881
+ text = text.replace(/(\*\*|__)(?=\S)([^\r]*?\S[*_]*)\1/g, '<strong>$2</strong>')
1882
+ text = text.replace(/(\*|_)(?=\S)([^\r]*?\S)\1/g, '<em>$2</em>')
1883
+ }
1884
+
1885
+ text = globals.converter._dispatch('italicsAndBold.after', text, options, globals)
1886
+ return text
1887
+ })
1888
+
1889
+ /**
1890
+ * Form HTML ordered (numbered) and unordered (bulleted) lists.
1891
+ */
1892
+ showdown.subParser('lists', function (text, options, globals) {
1893
+ 'use strict'
1894
+
1895
+ text = globals.converter._dispatch('lists.before', text, options, globals)
1896
+ /**
1897
+ * Process the contents of a single ordered or unordered list, splitting it
1898
+ * into individual list items.
1899
+ * @param {string} listStr
1900
+ * @param {boolean} trimTrailing
1901
+ * @returns {string}
1902
+ */
1903
+ function processListItems(listStr, trimTrailing) {
1904
+ globals.gListLevel++
1905
+
1906
+ // trim trailing blank lines:
1907
+ listStr = listStr.replace(/\n{2,}$/, '\n')
1908
+
1909
+ // attacklab: add sentinel to emulate \z
1910
+ listStr += '~0'
1911
+
1912
+ var rgx =
1913
+ /(\n)?(^[ \t]*)([*+-]|\d+[.])[ \t]+((\[(x|X| )?])?[ \t]*[^\r]+?(\n{1,2}))(?=\n*(~0|\2([*+-]|\d+[.])[ \t]+))/gm,
1914
+ isParagraphed = /\n[ \t]*\n(?!~0)/.test(listStr)
1915
+
1916
+ listStr = listStr.replace(rgx, function (wholeMatch, m1, m2, m3, m4, taskbtn, checked) {
1917
+ checked = checked && checked.trim() !== ''
1918
+ var item = showdown.subParser('outdent')(m4, options, globals),
1919
+ bulletStyle = ''
1920
+
1921
+ // Support for github tasklists
1922
+ if (taskbtn && options.tasklists) {
1923
+ bulletStyle = ' class="task-list-item" style="list-style-type: none;"'
1924
+ item = item.replace(/^[ \t]*\[(x|X| )?]/m, function () {
1925
+ var otp = '<input type="checkbox" disabled style="margin: 0px 0.35em 0.25em -1.6em; vertical-align: middle;"'
1926
+ if (checked) {
1927
+ otp += ' checked'
1928
+ }
1929
+ otp += '>'
1930
+ return otp
1931
+ })
1932
+ }
1933
+ if (m1 || item.search(/\n{2,}/) > -1) {
1934
+ item = showdown.subParser('githubCodeBlocks')(item, options, globals)
1935
+ item = showdown.subParser('blockGamut')(item, options, globals)
1936
+ } else {
1937
+ // Recursion for sub-lists:
1938
+ item = showdown.subParser('lists')(item, options, globals)
1939
+ item = item.replace(/\n$/, '') // chomp(item)
1940
+ if (isParagraphed) {
1941
+ item = showdown.subParser('paragraphs')(item, options, globals)
1942
+ } else {
1943
+ item = showdown.subParser('spanGamut')(item, options, globals)
1944
+ }
1945
+ }
1946
+ item = '\n<li' + bulletStyle + '>' + item + '</li>\n'
1947
+ return item
1948
+ })
1949
+
1950
+ // attacklab: strip sentinel
1951
+ listStr = listStr.replace(/~0/g, '')
1952
+
1953
+ globals.gListLevel--
1954
+
1955
+ if (trimTrailing) {
1956
+ listStr = listStr.replace(/\s+$/, '')
1957
+ }
1958
+
1959
+ return listStr
1960
+ }
1961
+
1962
+ /**
1963
+ * Check and parse consecutive lists (better fix for issue #142)
1964
+ * @param {string} list
1965
+ * @param {string} listType
1966
+ * @param {boolean} trimTrailing
1967
+ * @returns {string}
1968
+ */
1969
+ function parseConsecutiveLists(list, listType, trimTrailing) {
1970
+ // check if we caught 2 or more consecutive lists by mistake
1971
+ // we use the counterRgx, meaning if listType is UL we look for UL and vice versa
1972
+ var counterRxg = listType === 'ul' ? /^ {0,2}\d+\.[ \t]/gm : /^ {0,2}[*+-][ \t]/gm,
1973
+ subLists = [],
1974
+ result = ''
1975
+
1976
+ if (list.search(counterRxg) !== -1) {
1977
+ ;(function parseCL(txt) {
1978
+ var pos = txt.search(counterRxg)
1979
+ if (pos !== -1) {
1980
+ // slice
1981
+ result +=
1982
+ '\n\n<' + listType + '>' + processListItems(txt.slice(0, pos), !!trimTrailing) + '</' + listType + '>\n\n'
1983
+
1984
+ // invert counterType and listType
1985
+ listType = listType === 'ul' ? 'ol' : 'ul'
1986
+ counterRxg = listType === 'ul' ? /^ {0,2}\d+\.[ \t]/gm : /^ {0,2}[*+-][ \t]/gm
1987
+
1988
+ //recurse
1989
+ parseCL(txt.slice(pos))
1990
+ } else {
1991
+ result += '\n\n<' + listType + '>' + processListItems(txt, !!trimTrailing) + '</' + listType + '>\n\n'
1992
+ }
1993
+ })(list)
1994
+ for (var i = 0; i < subLists.length; ++i) {}
1995
+ } else {
1996
+ result = '\n\n<' + listType + '>' + processListItems(list, !!trimTrailing) + '</' + listType + '>\n\n'
1997
+ }
1998
+
1999
+ return result
2000
+ }
2001
+
2002
+ // attacklab: add sentinel to hack around khtml/safari bug:
2003
+ // http://bugs.webkit.org/show_bug.cgi?id=11231
2004
+ text += '~0'
2005
+
2006
+ // Re-usable pattern to match any entire ul or ol list:
2007
+ var wholeList = /^(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm
2008
+
2009
+ if (globals.gListLevel) {
2010
+ text = text.replace(wholeList, function (wholeMatch, list, m2) {
2011
+ var listType = m2.search(/[*+-]/g) > -1 ? 'ul' : 'ol'
2012
+ return parseConsecutiveLists(list, listType, true)
2013
+ })
2014
+ } else {
2015
+ wholeList = /(\n\n|^\n?)(([ ]{0,3}([*+-]|\d+[.])[ \t]+)[^\r]+?(~0|\n{2,}(?=\S)(?![ \t]*(?:[*+-]|\d+[.])[ \t]+)))/gm
2016
+ //wholeList = /(\n\n|^\n?)( {0,3}([*+-]|\d+\.)[ \t]+[\s\S]+?)(?=(~0)|(\n\n(?!\t| {2,}| {0,3}([*+-]|\d+\.)[ \t])))/g;
2017
+ text = text.replace(wholeList, function (wholeMatch, m1, list, m3) {
2018
+ var listType = m3.search(/[*+-]/g) > -1 ? 'ul' : 'ol'
2019
+ return parseConsecutiveLists(list, listType)
2020
+ })
2021
+ }
2022
+
2023
+ // attacklab: strip sentinel
2024
+ text = text.replace(/~0/, '')
2025
+
2026
+ text = globals.converter._dispatch('lists.after', text, options, globals)
2027
+ return text
2028
+ })
2029
+
2030
+ /**
2031
+ * Remove one level of line-leading tabs or spaces
2032
+ */
2033
+ showdown.subParser('outdent', function (text) {
2034
+ 'use strict'
2035
+
2036
+ // attacklab: hack around Konqueror 3.5.4 bug:
2037
+ // "----------bug".replace(/^-/g,"") == "bug"
2038
+ text = text.replace(/^(\t|[ ]{1,4})/gm, '~0') // attacklab: g_tab_width
2039
+
2040
+ // attacklab: clean up hack
2041
+ text = text.replace(/~0/g, '')
2042
+
2043
+ return text
2044
+ })
2045
+
2046
+ /**
2047
+ *
2048
+ */
2049
+ showdown.subParser('paragraphs', function (text, options, globals) {
2050
+ 'use strict'
2051
+
2052
+ text = globals.converter._dispatch('paragraphs.before', text, options, globals)
2053
+ // Strip leading and trailing lines:
2054
+ text = text.replace(/^\n+/g, '')
2055
+ text = text.replace(/\n+$/g, '')
2056
+
2057
+ var grafs = text.split(/\n{2,}/g),
2058
+ grafsOut = [],
2059
+ end = grafs.length // Wrap <p> tags
2060
+
2061
+ for (var i = 0; i < end; i++) {
2062
+ var str = grafs[i]
2063
+ // if this is an HTML marker, copy it
2064
+ if (str.search(/~(K|G)(\d+)\1/g) >= 0) {
2065
+ grafsOut.push(str)
2066
+ } else {
2067
+ str = showdown.subParser('spanGamut')(str, options, globals)
2068
+ str = str.replace(/^([ \t]*)/g, '<p>')
2069
+ str += '</p>'
2070
+ grafsOut.push(str)
2071
+ }
2072
+ }
2073
+
2074
+ /** Unhashify HTML blocks */
2075
+ end = grafsOut.length
2076
+ for (i = 0; i < end; i++) {
2077
+ var blockText = '',
2078
+ grafsOutIt = grafsOut[i],
2079
+ codeFlag = false
2080
+ // if this is a marker for an html block...
2081
+ while (grafsOutIt.search(/~(K|G)(\d+)\1/) >= 0) {
2082
+ var delim = RegExp.$1,
2083
+ num = RegExp.$2
2084
+
2085
+ if (delim === 'K') {
2086
+ blockText = globals.gHtmlBlocks[num]
2087
+ } else {
2088
+ // we need to check if ghBlock is a false positive
2089
+ if (codeFlag) {
2090
+ // use encoded version of all text
2091
+ blockText = showdown.subParser('encodeCode')(globals.ghCodeBlocks[num].text)
2092
+ } else {
2093
+ blockText = globals.ghCodeBlocks[num].codeblock
2094
+ }
2095
+ }
2096
+ blockText = blockText.replace(/\$/g, '$$$$') // Escape any dollar signs
2097
+
2098
+ grafsOutIt = grafsOutIt.replace(/(\n\n)?~(K|G)\d+\2(\n\n)?/, blockText)
2099
+ // Check if grafsOutIt is a pre->code
2100
+ if (/^<pre\b[^>]*>\s*<code\b[^>]*>/.test(grafsOutIt)) {
2101
+ codeFlag = true
2102
+ }
2103
+ }
2104
+ grafsOut[i] = grafsOutIt
2105
+ }
2106
+ text = grafsOut.join('\n\n')
2107
+ // Strip leading and trailing lines:
2108
+ text = text.replace(/^\n+/g, '')
2109
+ text = text.replace(/\n+$/g, '')
2110
+ return globals.converter._dispatch('paragraphs.after', text, options, globals)
2111
+ })
2112
+
2113
+ /**
2114
+ * Run extension
2115
+ */
2116
+ showdown.subParser('runExtension', function (ext, text, options, globals) {
2117
+ 'use strict'
2118
+
2119
+ if (ext.filter) {
2120
+ text = ext.filter(text, globals.converter, options)
2121
+ } else if (ext.regex) {
2122
+ // TODO remove this when old extension loading mechanism is deprecated
2123
+ var re = ext.regex
2124
+ if (!re instanceof RegExp) {
2125
+ re = new RegExp(re, 'g')
2126
+ }
2127
+ text = text.replace(re, ext.replace)
2128
+ }
2129
+
2130
+ return text
2131
+ })
2132
+
2133
+ /**
2134
+ * These are all the transformations that occur *within* block-level
2135
+ * tags like paragraphs, headers, and list items.
2136
+ */
2137
+ showdown.subParser('spanGamut', function (text, options, globals) {
2138
+ 'use strict'
2139
+
2140
+ text = globals.converter._dispatch('spanGamut.before', text, options, globals)
2141
+ text = showdown.subParser('codeSpans')(text, options, globals)
2142
+ text = showdown.subParser('escapeSpecialCharsWithinTagAttributes')(text, options, globals)
2143
+ text = showdown.subParser('encodeBackslashEscapes')(text, options, globals)
2144
+ text = showdown.subParser('images')(text, options, globals)
2145
+ text = showdown.subParser('anchors')(text, options, globals)
2146
+
2147
+ text = showdown.subParser('autoLinks')(text, options, globals)
2148
+ text = showdown.subParser('encodeAmpsAndAngles')(text, options, globals)
2149
+ text = showdown.subParser('italicsAndBold')(text, options, globals)
2150
+ text = showdown.subParser('strikethrough')(text, options, globals)
2151
+
2152
+ // Do hard breaks:
2153
+ text = text.replace(/ +\n/g, ' <br />\n')
2154
+
2155
+ text = globals.converter._dispatch('spanGamut.after', text, options, globals)
2156
+ return text
2157
+ })
2158
+
2159
+ showdown.subParser('strikethrough', function (text, options, globals) {
2160
+ 'use strict'
2161
+
2162
+ if (options.strikethrough) {
2163
+ text = globals.converter._dispatch('strikethrough.before', text, options, globals)
2164
+ text = text.replace(/(?:~T){2}([\s\S]+?)(?:~T){2}/g, '<del>$1</del>')
2165
+ text = globals.converter._dispatch('strikethrough.after', text, options, globals)
2166
+ }
2167
+
2168
+ return text
2169
+ })
2170
+
2171
+ /**
2172
+ * Strip any lines consisting only of spaces and tabs.
2173
+ * This makes subsequent regexs easier to write, because we can
2174
+ * match consecutive blank lines with /\n+/ instead of something
2175
+ * contorted like /[ \t]*\n+/
2176
+ */
2177
+ showdown.subParser('stripBlankLines', function (text) {
2178
+ 'use strict'
2179
+ return text.replace(/^[ \t]+$/gm, '')
2180
+ })
2181
+
2182
+ showdown.subParser('stripLinkDefinitions', function (text, options, globals) {
2183
+ 'use strict'
2184
+
2185
+ var regex =
2186
+ /^ {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
2187
+
2188
+ // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
2189
+ text += '~0'
2190
+
2191
+ text = text.replace(regex, function (wholeMatch, linkId, url, width, height, blankLines, title) {
2192
+ linkId = linkId.toLowerCase()
2193
+ globals.gUrls[linkId] = showdown.subParser('encodeAmpsAndAngles')(url) // Link IDs are case-insensitive
2194
+
2195
+ if (blankLines) {
2196
+ // Oops, found blank lines, so it's not a title.
2197
+ // Put back the parenthetical statement we stole.
2198
+ return blankLines + title
2199
+ } else {
2200
+ if (title) {
2201
+ globals.gTitles[linkId] = title.replace(/"|'/g, '&quot;')
2202
+ }
2203
+ if (options.parseImgDimensions && width && height) {
2204
+ globals.gDimensions[linkId] = {
2205
+ width: width,
2206
+ height: height,
2207
+ }
2208
+ }
2209
+ }
2210
+ // Completely remove the definition from the text
2211
+ return ''
2212
+ })
2213
+
2214
+ // attacklab: strip sentinel
2215
+ text = text.replace(/~0/, '')
2216
+
2217
+ return text
2218
+ })
2219
+
2220
+ showdown.subParser('tables', function (text, options, globals) {
2221
+ 'use strict'
2222
+
2223
+ if (!options.tables) {
2224
+ return text
2225
+ }
2226
+
2227
+ var tableRgx =
2228
+ /^[ \t]{0,3}\|?.+\|.+\n[ \t]{0,3}\|?[ \t]*:?[ \t]*(?:-|=){2,}[ \t]*:?[ \t]*\|[ \t]*:?[ \t]*(?:-|=){2,}[\s\S]+?(?:\n\n|~0)/gm
2229
+
2230
+ function parseStyles(sLine) {
2231
+ if (/^:[ \t]*--*$/.test(sLine)) {
2232
+ return ' style="text-align:left;"'
2233
+ } else if (/^--*[ \t]*:[ \t]*$/.test(sLine)) {
2234
+ return ' style="text-align:right;"'
2235
+ } else if (/^:[ \t]*--*[ \t]*:$/.test(sLine)) {
2236
+ return ' style="text-align:center;"'
2237
+ } else {
2238
+ return ''
2239
+ }
2240
+ }
2241
+
2242
+ function parseHeaders(header, style) {
2243
+ var id = ''
2244
+ header = header.trim()
2245
+ if (options.tableHeaderId) {
2246
+ id = ' id="' + header.replace(/ /g, '_').toLowerCase() + '"'
2247
+ }
2248
+ header = showdown.subParser('spanGamut')(header, options, globals)
2249
+
2250
+ return '<th' + id + style + '>' + header + '</th>\n'
2251
+ }
2252
+
2253
+ function parseCells(cell, style) {
2254
+ var subText = showdown.subParser('spanGamut')(cell, options, globals)
2255
+ return '<td' + style + '>' + subText + '</td>\n'
2256
+ }
2257
+
2258
+ function buildTable(headers, cells) {
2259
+ var tb = '<table>\n<thead>\n<tr>\n',
2260
+ tblLgn = headers.length
2261
+
2262
+ for (var i = 0; i < tblLgn; ++i) {
2263
+ tb += headers[i]
2264
+ }
2265
+ tb += '</tr>\n</thead>\n<tbody>\n'
2266
+
2267
+ for (i = 0; i < cells.length; ++i) {
2268
+ tb += '<tr>\n'
2269
+ for (var ii = 0; ii < tblLgn; ++ii) {
2270
+ tb += cells[i][ii]
2271
+ }
2272
+ tb += '</tr>\n'
2273
+ }
2274
+ tb += '</tbody>\n</table>\n'
2275
+ return tb
2276
+ }
2277
+
2278
+ text = globals.converter._dispatch('tables.before', text, options, globals)
2279
+
2280
+ text = text.replace(tableRgx, function (rawTable) {
2281
+ var i,
2282
+ tableLines = rawTable.split('\n')
2283
+
2284
+ // strip wrong first and last column if wrapped tables are used
2285
+ for (i = 0; i < tableLines.length; ++i) {
2286
+ if (/^[ \t]{0,3}\|/.test(tableLines[i])) {
2287
+ tableLines[i] = tableLines[i].replace(/^[ \t]{0,3}\|/, '')
2288
+ }
2289
+ if (/\|[ \t]*$/.test(tableLines[i])) {
2290
+ tableLines[i] = tableLines[i].replace(/\|[ \t]*$/, '')
2291
+ }
2292
+ }
2293
+
2294
+ var rawHeaders = tableLines[0].split('|').map(function (s) {
2295
+ return s.trim()
2296
+ }),
2297
+ rawStyles = tableLines[1].split('|').map(function (s) {
2298
+ return s.trim()
2299
+ }),
2300
+ rawCells = [],
2301
+ headers = [],
2302
+ styles = [],
2303
+ cells = []
2304
+
2305
+ tableLines.shift()
2306
+ tableLines.shift()
2307
+
2308
+ for (i = 0; i < tableLines.length; ++i) {
2309
+ if (tableLines[i].trim() === '') {
2310
+ continue
2311
+ }
2312
+ rawCells.push(
2313
+ tableLines[i].split('|').map(function (s) {
2314
+ return s.trim()
2315
+ }),
2316
+ )
2317
+ }
2318
+
2319
+ if (rawHeaders.length < rawStyles.length) {
2320
+ return rawTable
2321
+ }
2322
+
2323
+ for (i = 0; i < rawStyles.length; ++i) {
2324
+ styles.push(parseStyles(rawStyles[i]))
2325
+ }
2326
+
2327
+ for (i = 0; i < rawHeaders.length; ++i) {
2328
+ if (showdown.helper.isUndefined(styles[i])) {
2329
+ styles[i] = ''
2330
+ }
2331
+ headers.push(parseHeaders(rawHeaders[i], styles[i]))
2332
+ }
2333
+
2334
+ for (i = 0; i < rawCells.length; ++i) {
2335
+ var row = []
2336
+ for (var ii = 0; ii < headers.length; ++ii) {
2337
+ if (showdown.helper.isUndefined(rawCells[i][ii])) {
2338
+ }
2339
+ row.push(parseCells(rawCells[i][ii], styles[ii]))
2340
+ }
2341
+ cells.push(row)
2342
+ }
2343
+
2344
+ return buildTable(headers, cells)
2345
+ })
2346
+
2347
+ text = globals.converter._dispatch('tables.after', text, options, globals)
2348
+
2349
+ return text
2350
+ })
2351
+
2352
+ /**
2353
+ * Swap back in all the special characters we've hidden.
2354
+ */
2355
+ showdown.subParser('unescapeSpecialChars', function (text) {
2356
+ 'use strict'
2357
+
2358
+ text = text.replace(/~E(\d+)E/g, function (wholeMatch, m1) {
2359
+ var charCodeToReplace = parseInt(m1)
2360
+ return String.fromCharCode(charCodeToReplace)
2361
+ })
2362
+ return text
2363
+ })
2364
+ module.exports = showdown