aboutsummaryrefslogtreecommitdiff
path: root/js/stmd.js
blob: 24651fb145568a08ff463b23dc042318f224ddc6 (plain)
  1. // stmd.js - CommomMark in javascript
  2. // Copyright (C) 2014 John MacFarlane
  3. // License: BSD3.
  4. // Basic usage:
  5. //
  6. // var stmd = require('stmd');
  7. // var parser = new stmd.DocParser();
  8. // var renderer = new stmd.HtmlRenderer();
  9. // console.log(renderer.render(parser.parse('Hello *world*')));
  10. (function(exports) {
  11. var entities = { AAacute: 'Á',
  12. aacute: 'á',
  13. Abreve: 'Ă',
  14. abreve: 'ă',
  15. ac: '∾',
  16. acd: '∿',
  17. acE: '∾',
  18. Acirc: 'Â',
  19. acirc: 'â',
  20. acute: '´',
  21. Acy: 'А',
  22. acy: 'а',
  23. AElig: 'Æ',
  24. aelig: 'æ',
  25. af: '⁡',
  26. Afr: '𝔄',
  27. afr: '𝔞',
  28. Agrave: 'À',
  29. agrave: 'à',
  30. alefsym: 'ℵ',
  31. aleph: 'ℵ',
  32. Alpha: 'Α',
  33. alpha: 'α',
  34. Amacr: 'Ā',
  35. amacr: 'ā',
  36. amalg: '⨿',
  37. amp: '&',
  38. AMP: '&',
  39. andand: '⩕',
  40. And: '⩓',
  41. and: '∧',
  42. andd: '⩜',
  43. andslope: '⩘',
  44. andv: '⩚',
  45. ang: '∠',
  46. ange: '⦤',
  47. angle: '∠',
  48. angmsdaa: '⦨',
  49. angmsdab: '⦩',
  50. angmsdac: '⦪',
  51. angmsdad: '⦫',
  52. angmsdae: '⦬',
  53. angmsdaf: '⦭',
  54. angmsdag: '⦮',
  55. angmsdah: '⦯',
  56. angmsd: '∡',
  57. angrt: '∟',
  58. angrtvb: '⊾',
  59. angrtvbd: '⦝',
  60. angsph: '∢',
  61. angst: 'Å',
  62. angzarr: '⍼',
  63. Aogon: 'Ą',
  64. aogon: 'ą',
  65. Aopf: '𝔸',
  66. aopf: '𝕒',
  67. apacir: '⩯',
  68. ap: '≈',
  69. apE: '⩰',
  70. ape: '≊',
  71. apid: '≋',
  72. apos: '\'',
  73. ApplyFunction: '⁡',
  74. approx: '≈',
  75. approxeq: '≊',
  76. Aring: 'Å',
  77. aring: 'å',
  78. Ascr: '𝒜',
  79. ascr: '𝒶',
  80. Assign: '≔',
  81. ast: '*',
  82. asymp: '≈',
  83. asympeq: '≍',
  84. Atilde: 'Ã',
  85. atilde: 'ã',
  86. Auml: 'Ä',
  87. auml: 'ä',
  88. awconint: '∳',
  89. awint: '⨑',
  90. backcong: '≌',
  91. backepsilon: '϶',
  92. backprime: '‵',
  93. backsim: '∽',
  94. backsimeq: '⋍',
  95. Backslash: '∖',
  96. Barv: '⫧',
  97. barvee: '⊽',
  98. barwed: '⌅',
  99. Barwed: '⌆',
  100. barwedge: '⌅',
  101. bbrk: '⎵',
  102. bbrktbrk: '⎶',
  103. bcong: '≌',
  104. Bcy: 'Б',
  105. bcy: 'б',
  106. bdquo: '„',
  107. becaus: '∵',
  108. because: '∵',
  109. Because: '∵',
  110. bemptyv: '⦰',
  111. bepsi: '϶',
  112. bernou: 'ℬ',
  113. Bernoullis: 'ℬ',
  114. Beta: 'Β',
  115. beta: 'β',
  116. beth: 'ℶ',
  117. between: '≬',
  118. Bfr: '𝔅',
  119. bfr: '𝔟',
  120. bigcap: '⋂',
  121. bigcirc: '◯',
  122. bigcup: '⋃',
  123. bigodot: '⨀',
  124. bigoplus: '⨁',
  125. bigotimes: '⨂',
  126. bigsqcup: '⨆',
  127. bigstar: '★',
  128. bigtriangledown: '▽',
  129. bigtriangleup: '△',
  130. biguplus: '⨄',
  131. bigvee: '⋁',
  132. bigwedge: '⋀',
  133. bkarow: '⤍',
  134. blacklozenge: '⧫',
  135. blacksquare: '▪',
  136. blacktriangle: '▴',
  137. blacktriangledown: '▾',
  138. blacktriangleleft: '◂',
  139. blacktriangleright: '▸',
  140. blank: '␣',
  141. blk12: '▒',
  142. blk14: '░',
  143. blk34: '▓',
  144. block: '█',
  145. bne: '=',
  146. bnequiv: '≡',
  147. bNot: '⫭',
  148. bnot: '⌐',
  149. Bopf: '𝔹',
  150. bopf: '𝕓',
  151. bot: '⊥',
  152. bottom: '⊥',
  153. bowtie: '⋈',
  154. boxbox: '⧉',
  155. boxdl: '┐',
  156. boxdL: '╕',
  157. boxDl: '╖',
  158. boxDL: '╗',
  159. boxdr: '┌',
  160. boxdR: '╒',
  161. boxDr: '╓',
  162. boxDR: '╔',
  163. boxh: '─',
  164. boxH: '═',
  165. boxhd: '┬',
  166. boxHd: '╤',
  167. boxhD: '╥',
  168. boxHD: '╦',
  169. boxhu: '┴',
  170. boxHu: '╧',
  171. boxhU: '╨',
  172. boxHU: '╩',
  173. boxminus: '⊟',
  174. boxplus: '⊞',
  175. boxtimes: '⊠',
  176. boxul: '┘',
  177. boxuL: '╛',
  178. boxUl: '╜',
  179. boxUL: '╝',
  180. boxur: '└',
  181. boxuR: '╘',
  182. boxUr: '╙',
  183. boxUR: '╚',
  184. boxv: '│',
  185. boxV: '║',
  186. boxvh: '┼',
  187. boxvH: '╪',
  188. boxVh: '╫',
  189. boxVH: '╬',
  190. boxvl: '┤',
  191. boxvL: '╡',
  192. boxVl: '╢',
  193. boxVL: '╣',
  194. boxvr: '├',
  195. boxvR: '╞',
  196. boxVr: '╟',
  197. boxVR: '╠',
  198. bprime: '‵',
  199. breve: '˘',
  200. Breve: '˘',
  201. brvbar: '¦',
  202. bscr: '𝒷',
  203. Bscr: 'ℬ',
  204. bsemi: '⁏',
  205. bsim: '∽',
  206. bsime: '⋍',
  207. bsolb: '⧅',
  208. bsol: '\\',
  209. bsolhsub: '⟈',
  210. bull: '•',
  211. bullet: '•',
  212. bump: '≎',
  213. bumpE: '⪮',
  214. bumpe: '≏',
  215. Bumpeq: '≎',
  216. bumpeq: '≏',
  217. Cacute: 'Ć',
  218. cacute: 'ć',
  219. capand: '⩄',
  220. capbrcup: '⩉',
  221. capcap: '⩋',
  222. cap: '∩',
  223. Cap: '⋒',
  224. capcup: '⩇',
  225. capdot: '⩀',
  226. CapitalDifferentialD: 'ⅅ',
  227. caps: '∩',
  228. caret: '⁁',
  229. caron: 'ˇ',
  230. Cayleys: 'ℭ',
  231. ccaps: '⩍',
  232. Ccaron: 'Č',
  233. ccaron: 'č',
  234. Ccedil: 'Ç',
  235. ccedil: 'ç',
  236. Ccirc: 'Ĉ',
  237. ccirc: 'ĉ',
  238. Cconint: '∰',
  239. ccups: '⩌',
  240. ccupssm: '⩐',
  241. Cdot: 'Ċ',
  242. cdot: 'ċ',
  243. cedil: '¸',
  244. Cedilla: '¸',
  245. cemptyv: '⦲',
  246. cent: '¢',
  247. centerdot: '·',
  248. CenterDot: '·',
  249. cfr: '𝔠',
  250. Cfr: 'ℭ',
  251. CHcy: 'Ч',
  252. chcy: 'ч',
  253. check: '✓',
  254. checkmark: '✓',
  255. Chi: 'Χ',
  256. chi: 'χ',
  257. circ: 'ˆ',
  258. circeq: '≗',
  259. circlearrowleft: '↺',
  260. circlearrowright: '↻',
  261. circledast: '⊛',
  262. circledcirc: '⊚',
  263. circleddash: '⊝',
  264. CircleDot: '⊙',
  265. circledR: '®',
  266. circledS: 'Ⓢ',
  267. CircleMinus: '⊖',
  268. CirclePlus: '⊕',
  269. CircleTimes: '⊗',
  270. cir: '○',
  271. cirE: '⧃',
  272. cire: '≗',
  273. cirfnint: '⨐',
  274. cirmid: '⫯',
  275. cirscir: '⧂',
  276. ClockwiseContourIntegral: '∲',
  277. CloseCurlyDoubleQuote: '”',
  278. CloseCurlyQuote: '’',
  279. clubs: '♣',
  280. clubsuit: '♣',
  281. colon: ':',
  282. Colon: '∷',
  283. Colone: '⩴',
  284. colone: '≔',
  285. coloneq: '≔',
  286. comma: ',',
  287. commat: '@',
  288. comp: '∁',
  289. compfn: '∘',
  290. complement: '∁',
  291. complexes: 'ℂ',
  292. cong: '≅',
  293. congdot: '⩭',
  294. Congruent: '≡',
  295. conint: '∮',
  296. Conint: '∯',
  297. ContourIntegral: '∮',
  298. copf: '𝕔',
  299. Copf: 'ℂ',
  300. coprod: '∐',
  301. Coproduct: '∐',
  302. copy: '©',
  303. COPY: '©',
  304. copysr: '℗',
  305. CounterClockwiseContourIntegral: '∳',
  306. crarr: '↵',
  307. cross: '✗',
  308. Cross: '⨯',
  309. Cscr: '𝒞',
  310. cscr: '𝒸',
  311. csub: '⫏',
  312. csube: '⫑',
  313. csup: '⫐',
  314. csupe: '⫒',
  315. ctdot: '⋯',
  316. cudarrl: '⤸',
  317. cudarrr: '⤵',
  318. cuepr: '⋞',
  319. cuesc: '⋟',
  320. cularr: '↶',
  321. cularrp: '⤽',
  322. cupbrcap: '⩈',
  323. cupcap: '⩆',
  324. CupCap: '≍',
  325. cup: '∪',
  326. Cup: '⋓',
  327. cupcup: '⩊',
  328. cupdot: '⊍',
  329. cupor: '⩅',
  330. cups: '∪',
  331. curarr: '↷',
  332. curarrm: '⤼',
  333. curlyeqprec: '⋞',
  334. curlyeqsucc: '⋟',
  335. curlyvee: '⋎',
  336. curlywedge: '⋏',
  337. curren: '¤',
  338. curvearrowleft: '↶',
  339. curvearrowright: '↷',
  340. cuvee: '⋎',
  341. cuwed: '⋏',
  342. cwconint: '∲',
  343. cwint: '∱',
  344. cylcty: '⌭',
  345. dagger: '†',
  346. Dagger: '‡',
  347. daleth: 'ℸ',
  348. darr: '↓',
  349. Darr: '↡',
  350. dArr: '⇓',
  351. dash: '‐',
  352. Dashv: '⫤',
  353. dashv: '⊣',
  354. dbkarow: '⤏',
  355. dblac: '˝',
  356. Dcaron: 'Ď',
  357. dcaron: 'ď',
  358. Dcy: 'Д',
  359. dcy: 'д',
  360. ddagger: '‡',
  361. ddarr: '⇊',
  362. DD: 'ⅅ',
  363. dd: 'ⅆ',
  364. DDotrahd: '⤑',
  365. ddotseq: '⩷',
  366. deg: '°',
  367. Del: '∇',
  368. Delta: 'Δ',
  369. delta: 'δ',
  370. demptyv: '⦱',
  371. dfisht: '⥿',
  372. Dfr: '𝔇',
  373. dfr: '𝔡',
  374. dHar: '⥥',
  375. dharl: '⇃',
  376. dharr: '⇂',
  377. DiacriticalAcute: '´',
  378. DiacriticalDot: '˙',
  379. DiacriticalDoubleAcute: '˝',
  380. DiacriticalGrave: '`',
  381. DiacriticalTilde: '˜',
  382. diam: '⋄',
  383. diamond: '⋄',
  384. Diamond: '⋄',
  385. diamondsuit: '♦',
  386. diams: '♦',
  387. die: '¨',
  388. DifferentialD: 'ⅆ',
  389. digamma: 'ϝ',
  390. disin: '⋲',
  391. div: '÷',
  392. divide: '÷',
  393. divideontimes: '⋇',
  394. divonx: '⋇',
  395. DJcy: 'Ђ',
  396. djcy: 'ђ',
  397. dlcorn: '⌞',
  398. dlcrop: '⌍',
  399. dollar: '$',
  400. Dopf: '𝔻',
  401. dopf: '𝕕',
  402. Dot: '¨',
  403. dot: '˙',
  404. DotDot: '⃜',
  405. doteq: '≐',
  406. doteqdot: '≑',
  407. DotEqual: '≐',
  408. dotminus: '∸',
  409. dotplus: '∔',
  410. dotsquare: '⊡',
  411. doublebarwedge: '⌆',
  412. DoubleContourIntegral: '∯',
  413. DoubleDot: '¨',
  414. DoubleDownArrow: '⇓',
  415. DoubleLeftArrow: '⇐',
  416. DoubleLeftRightArrow: '⇔',
  417. DoubleLeftTee: '⫤',
  418. DoubleLongLeftArrow: '⟸',
  419. DoubleLongLeftRightArrow: '⟺',
  420. DoubleLongRightArrow: '⟹',
  421. DoubleRightArrow: '⇒',
  422. DoubleRightTee: '⊨',
  423. DoubleUpArrow: '⇑',
  424. DoubleUpDownArrow: '⇕',
  425. DoubleVerticalBar: '∥',
  426. DownArrowBar: '⤓',
  427. downarrow: '↓',
  428. DownArrow: '↓',
  429. Downarrow: '⇓',
  430. DownArrowUpArrow: '⇵',
  431. DownBreve: '̑',
  432. downdownarrows: '⇊',
  433. downharpoonleft: '⇃',
  434. downharpoonright: '⇂',
  435. DownLeftRightVector: '⥐',
  436. DownLeftTeeVector: '⥞',
  437. DownLeftVectorBar: '⥖',
  438. DownLeftVector: '↽',
  439. DownRightTeeVector: '⥟',
  440. DownRightVectorBar: '⥗',
  441. DownRightVector: '⇁',
  442. DownTeeArrow: '↧',
  443. DownTee: '⊤',
  444. drbkarow: '⤐',
  445. drcorn: '⌟',
  446. drcrop: '⌌',
  447. Dscr: '𝒟',
  448. dscr: '𝒹',
  449. DScy: 'Ѕ',
  450. dscy: 'ѕ',
  451. dsol: '⧶',
  452. Dstrok: 'Đ',
  453. dstrok: 'đ',
  454. dtdot: '⋱',
  455. dtri: '▿',
  456. dtrif: '▾',
  457. duarr: '⇵',
  458. duhar: '⥯',
  459. dwangle: '⦦',
  460. DZcy: 'Џ',
  461. dzcy: 'џ',
  462. dzigrarr: '⟿',
  463. Eacute: 'É',
  464. eacute: 'é',
  465. easter: '⩮',
  466. Ecaron: 'Ě',
  467. ecaron: 'ě',
  468. Ecirc: 'Ê',
  469. ecirc: 'ê',
  470. ecir: '≖',
  471. ecolon: '≕',
  472. Ecy: 'Э',
  473. ecy: 'э',
  474. eDDot: '⩷',
  475. Edot: 'Ė',
  476. edot: 'ė',
  477. eDot: '≑',
  478. ee: 'ⅇ',
  479. efDot: '≒',
  480. Efr: '𝔈',
  481. efr: '𝔢',
  482. eg: '⪚',
  483. Egrave: 'È',
  484. egrave: 'è',
  485. egs: '⪖',
  486. egsdot: '⪘',
  487. el: '⪙',
  488. Element: '∈',
  489. elinters: '⏧',
  490. ell: 'ℓ',
  491. els: '⪕',
  492. elsdot: '⪗',
  493. Emacr: 'Ē',
  494. emacr: 'ē',
  495. empty: '∅',
  496. emptyset: '∅',
  497. EmptySmallSquare: '◻',
  498. emptyv: '∅',
  499. EmptyVerySmallSquare: '▫',
  500. emsp13: ' ',
  501. emsp14: ' ',
  502. emsp: ' ',
  503. ENG: 'Ŋ',
  504. eng: 'ŋ',
  505. ensp: ' ',
  506. Eogon: 'Ę',
  507. eogon: 'ę',
  508. Eopf: '𝔼',
  509. eopf: '𝕖',
  510. epar: '⋕',
  511. eparsl: '⧣',
  512. eplus: '⩱',
  513. epsi: 'ε',
  514. Epsilon: 'Ε',
  515. epsilon: 'ε',
  516. epsiv: 'ϵ',
  517. eqcirc: '≖',
  518. eqcolon: '≕',
  519. eqsim: '≂',
  520. eqslantgtr: '⪖',
  521. eqslantless: '⪕',
  522. Equal: '⩵',
  523. equals: '=',
  524. EqualTilde: '≂',
  525. equest: '≟',
  526. Equilibrium: '⇌',
  527. equiv: '≡',
  528. equivDD: '⩸',
  529. eqvparsl: '⧥',
  530. erarr: '⥱',
  531. erDot: '≓',
  532. escr: 'ℯ',
  533. Escr: 'ℰ',
  534. esdot: '≐',
  535. Esim: '⩳',
  536. esim: '≂',
  537. Eta: 'Η',
  538. eta: 'η',
  539. ETH: 'Ð',
  540. eth: 'ð',
  541. Euml: 'Ë',
  542. euml: 'ë',
  543. euro: '€',
  544. excl: '!',
  545. exist: '∃',
  546. Exists: '∃',
  547. expectation: 'ℰ',
  548. exponentiale: 'ⅇ',
  549. ExponentialE: 'ⅇ',
  550. fallingdotseq: '≒',
  551. Fcy: 'Ф',
  552. fcy: 'ф',
  553. female: '♀',
  554. ffilig: 'ffi',
  555. fflig: 'ff',
  556. ffllig: 'ffl',
  557. Ffr: '𝔉',
  558. ffr: '𝔣',
  559. filig: 'fi',
  560. FilledSmallSquare: '◼',
  561. FilledVerySmallSquare: '▪',
  562. fjlig: 'f',
  563. flat: '♭',
  564. fllig: 'fl',
  565. fltns: '▱',
  566. fnof: 'ƒ',
  567. Fopf: '𝔽',
  568. fopf: '𝕗',
  569. forall: '∀',
  570. ForAll: '∀',
  571. fork: '⋔',
  572. forkv: '⫙',
  573. Fouriertrf: 'ℱ',
  574. fpartint: '⨍',
  575. frac12: '½',
  576. frac13: '⅓',
  577. frac14: '¼',
  578. frac15: '⅕',
  579. frac16: '⅙',
  580. frac18: '⅛',
  581. frac23: '⅔',
  582. frac25: '⅖',
  583. frac34: '¾',
  584. frac35: '⅗',
  585. frac38: '⅜',
  586. frac45: '⅘',
  587. frac56: '⅚',
  588. frac58: '⅝',
  589. frac78: '⅞',
  590. frasl: '⁄',
  591. frown: '⌢',
  592. fscr: '𝒻',
  593. Fscr: 'ℱ',
  594. gacute: 'ǵ',
  595. Gamma: 'Γ',
  596. gamma: 'γ',
  597. Gammad: 'Ϝ',
  598. gammad: 'ϝ',
  599. gap: '⪆',
  600. Gbreve: 'Ğ',
  601. gbreve: 'ğ',
  602. Gcedil: 'Ģ',
  603. Gcirc: 'Ĝ',
  604. gcirc: 'ĝ',
  605. Gcy: 'Г',
  606. gcy: 'г',
  607. Gdot: 'Ġ',
  608. gdot: 'ġ',
  609. ge: '≥',
  610. gE: '≧',
  611. gEl: '⪌',
  612. gel: '⋛',
  613. geq: '≥',
  614. geqq: '≧',
  615. geqslant: '⩾',
  616. gescc: '⪩',
  617. ges: '⩾',
  618. gesdot: '⪀',
  619. gesdoto: '⪂',
  620. gesdotol: '⪄',
  621. gesl: '⋛',
  622. gesles: '⪔',
  623. Gfr: '𝔊',
  624. gfr: '𝔤',
  625. gg: '≫',
  626. Gg: '⋙',
  627. ggg: '⋙',
  628. gimel: 'ℷ',
  629. GJcy: 'Ѓ',
  630. gjcy: 'ѓ',
  631. gla: '⪥',
  632. gl: '≷',
  633. glE: '⪒',
  634. glj: '⪤',
  635. gnap: '⪊',
  636. gnapprox: '⪊',
  637. gne: '⪈',
  638. gnE: '≩',
  639. gneq: '⪈',
  640. gneqq: '≩',
  641. gnsim: '⋧',
  642. Gopf: '𝔾',
  643. gopf: '𝕘',
  644. grave: '`',
  645. GreaterEqual: '≥',
  646. GreaterEqualLess: '⋛',
  647. GreaterFullEqual: '≧',
  648. GreaterGreater: '⪢',
  649. GreaterLess: '≷',
  650. GreaterSlantEqual: '⩾',
  651. GreaterTilde: '≳',
  652. Gscr: '𝒢',
  653. gscr: 'ℊ',
  654. gsim: '≳',
  655. gsime: '⪎',
  656. gsiml: '⪐',
  657. gtcc: '⪧',
  658. gtcir: '⩺',
  659. gt: '>',
  660. GT: '>',
  661. Gt: '≫',
  662. gtdot: '⋗',
  663. gtlPar: '⦕',
  664. gtquest: '⩼',
  665. gtrapprox: '⪆',
  666. gtrarr: '⥸',
  667. gtrdot: '⋗',
  668. gtreqless: '⋛',
  669. gtreqqless: '⪌',
  670. gtrless: '≷',
  671. gtrsim: '≳',
  672. gvertneqq: '≩',
  673. gvnE: '≩',
  674. Hacek: 'ˇ',
  675. hairsp: ' ',
  676. half: '½',
  677. hamilt: 'ℋ',
  678. HARDcy: 'Ъ',
  679. hardcy: 'ъ',
  680. harrcir: '⥈',
  681. harr: '↔',
  682. hArr: '⇔',
  683. harrw: '↭',
  684. Hat: '^',
  685. hbar: 'ℏ',
  686. Hcirc: 'Ĥ',
  687. hcirc: 'ĥ',
  688. hearts: '♥',
  689. heartsuit: '♥',
  690. hellip: '…',
  691. hercon: '⊹',
  692. hfr: '𝔥',
  693. Hfr: 'ℌ',
  694. HilbertSpace: 'ℋ',
  695. hksearow: '⤥',
  696. hkswarow: '⤦',
  697. hoarr: '⇿',
  698. homtht: '∻',
  699. hookleftarrow: '↩',
  700. hookrightarrow: '↪',
  701. hopf: '𝕙',
  702. Hopf: 'ℍ',
  703. horbar: '―',
  704. HorizontalLine: '─',
  705. hscr: '𝒽',
  706. Hscr: 'ℋ',
  707. hslash: 'ℏ',
  708. Hstrok: 'Ħ',
  709. hstrok: 'ħ',
  710. HumpDownHump: '≎',
  711. HumpEqual: '≏',
  712. hybull: '⁃',
  713. hyphen: '‐',
  714. Iacute: 'Í',
  715. iacute: 'í',
  716. ic: '⁣',
  717. Icirc: 'Î',
  718. icirc: 'î',
  719. Icy: 'И',
  720. icy: 'и',
  721. Idot: 'İ',
  722. IEcy: 'Е',
  723. iecy: 'е',
  724. iexcl: '¡',
  725. iff: '⇔',
  726. ifr: '𝔦',
  727. Ifr: 'ℑ',
  728. Igrave: 'Ì',
  729. igrave: 'ì',
  730. ii: 'ⅈ',
  731. iiiint: '⨌',
  732. iiint: '∭',
  733. iinfin: '⧜',
  734. iiota: '℩',
  735. IJlig: 'IJ',
  736. ijlig: 'ij',
  737. Imacr: 'Ī',
  738. imacr: 'ī',
  739. image: 'ℑ',
  740. ImaginaryI: 'ⅈ',
  741. imagline: 'ℐ',
  742. imagpart: 'ℑ',
  743. imath: 'ı',
  744. Im: 'ℑ',
  745. imof: '⊷',
  746. imped: 'Ƶ',
  747. Implies: '⇒',
  748. incare: '℅',
  749. in: '∈',
  750. infin: '∞',
  751. infintie: '⧝',
  752. inodot: 'ı',
  753. intcal: '⊺',
  754. int: '∫',
  755. Int: '∬',
  756. integers: 'ℤ',
  757. Integral: '∫',
  758. intercal: '⊺',
  759. Intersection: '⋂',
  760. intlarhk: '⨗',
  761. intprod: '⨼',
  762. InvisibleComma: '⁣',
  763. InvisibleTimes: '⁢',
  764. IOcy: 'Ё',
  765. iocy: 'ё',
  766. Iogon: 'Į',
  767. iogon: 'į',
  768. Iopf: '𝕀',
  769. iopf: '𝕚',
  770. Iota: 'Ι',
  771. iota: 'ι',
  772. iprod: '⨼',
  773. iquest: '¿',
  774. iscr: '𝒾',
  775. Iscr: 'ℐ',
  776. isin: '∈',
  777. isindot: '⋵',
  778. isinE: '⋹',
  779. isins: '⋴',
  780. isinsv: '⋳',
  781. isinv: '∈',
  782. it: '⁢',
  783. Itilde: 'Ĩ',
  784. itilde: 'ĩ',
  785. Iukcy: 'І',
  786. iukcy: 'і',
  787. Iuml: 'Ï',
  788. iuml: 'ï',
  789. Jcirc: 'Ĵ',
  790. jcirc: 'ĵ',
  791. Jcy: 'Й',
  792. jcy: 'й',
  793. Jfr: '𝔍',
  794. jfr: '𝔧',
  795. jmath: 'ȷ',
  796. Jopf: '𝕁',
  797. jopf: '𝕛',
  798. Jscr: '𝒥',
  799. jscr: '𝒿',
  800. Jsercy: 'Ј',
  801. jsercy: 'ј',
  802. Jukcy: 'Є',
  803. jukcy: 'є',
  804. Kappa: 'Κ',
  805. kappa: 'κ',
  806. kappav: 'ϰ',
  807. Kcedil: 'Ķ',
  808. kcedil: 'ķ',
  809. Kcy: 'К',
  810. kcy: 'к',
  811. Kfr: '𝔎',
  812. kfr: '𝔨',
  813. kgreen: 'ĸ',
  814. KHcy: 'Х',
  815. khcy: 'х',
  816. KJcy: 'Ќ',
  817. kjcy: 'ќ',
  818. Kopf: '𝕂',
  819. kopf: '𝕜',
  820. Kscr: '𝒦',
  821. kscr: '𝓀',
  822. lAarr: '⇚',
  823. Lacute: 'Ĺ',
  824. lacute: 'ĺ',
  825. laemptyv: '⦴',
  826. lagran: 'ℒ',
  827. Lambda: 'Λ',
  828. lambda: 'λ',
  829. lang: '⟨',
  830. Lang: '⟪',
  831. langd: '⦑',
  832. langle: '⟨',
  833. lap: '⪅',
  834. Laplacetrf: 'ℒ',
  835. laquo: '«',
  836. larrb: '⇤',
  837. larrbfs: '⤟',
  838. larr: '←',
  839. Larr: '↞',
  840. lArr: '⇐',
  841. larrfs: '⤝',
  842. larrhk: '↩',
  843. larrlp: '↫',
  844. larrpl: '⤹',
  845. larrsim: '⥳',
  846. larrtl: '↢',
  847. latail: '⤙',
  848. lAtail: '⤛',
  849. lat: '⪫',
  850. late: '⪭',
  851. lates: '⪭',
  852. lbarr: '⤌',
  853. lBarr: '⤎',
  854. lbbrk: '❲',
  855. lbrace: '{',
  856. lbrack: '[',
  857. lbrke: '⦋',
  858. lbrksld: '⦏',
  859. lbrkslu: '⦍',
  860. Lcaron: 'Ľ',
  861. lcaron: 'ľ',
  862. Lcedil: 'Ļ',
  863. lcedil: 'ļ',
  864. lceil: '⌈',
  865. lcub: '{',
  866. Lcy: 'Л',
  867. lcy: 'л',
  868. ldca: '⤶',
  869. ldquo: '“',
  870. ldquor: '„',
  871. ldrdhar: '⥧',
  872. ldrushar: '⥋',
  873. ldsh: '↲',
  874. le: '≤',
  875. lE: '≦',
  876. LeftAngleBracket: '⟨',
  877. LeftArrowBar: '⇤',
  878. leftarrow: '←',
  879. LeftArrow: '←',
  880. Leftarrow: '⇐',
  881. LeftArrowRightArrow: '⇆',
  882. leftarrowtail: '↢',
  883. LeftCeiling: '⌈',
  884. LeftDoubleBracket: '⟦',
  885. LeftDownTeeVector: '⥡',
  886. LeftDownVectorBar: '⥙',
  887. LeftDownVector: '⇃',
  888. LeftFloor: '⌊',
  889. leftharpoondown: '↽',
  890. leftharpoonup: '↼',
  891. leftleftarrows: '⇇',
  892. leftrightarrow: '↔',
  893. LeftRightArrow: '↔',
  894. Leftrightarrow: '⇔',
  895. leftrightarrows: '⇆',
  896. leftrightharpoons: '⇋',
  897. leftrightsquigarrow: '↭',
  898. LeftRightVector: '⥎',
  899. LeftTeeArrow: '↤',
  900. LeftTee: '⊣',
  901. LeftTeeVector: '⥚',
  902. leftthreetimes: '⋋',
  903. LeftTriangleBar: '⧏',
  904. LeftTriangle: '⊲',
  905. LeftTriangleEqual: '⊴',
  906. LeftUpDownVector: '⥑',
  907. LeftUpTeeVector: '⥠',
  908. LeftUpVectorBar: '⥘',
  909. LeftUpVector: '↿',
  910. LeftVectorBar: '⥒',
  911. LeftVector: '↼',
  912. lEg: '⪋',
  913. leg: '⋚',
  914. leq: '≤',
  915. leqq: '≦',
  916. leqslant: '⩽',
  917. lescc: '⪨',
  918. les: '⩽',
  919. lesdot: '⩿',
  920. lesdoto: '⪁',
  921. lesdotor: '⪃',
  922. lesg: '⋚',
  923. lesges: '⪓',
  924. lessapprox: '⪅',
  925. lessdot: '⋖',
  926. lesseqgtr: '⋚',
  927. lesseqqgtr: '⪋',
  928. LessEqualGreater: '⋚',
  929. LessFullEqual: '≦',
  930. LessGreater: '≶',
  931. lessgtr: '≶',
  932. LessLess: '⪡',
  933. lesssim: '≲',
  934. LessSlantEqual: '⩽',
  935. LessTilde: '≲',
  936. lfisht: '⥼',
  937. lfloor: '⌊',
  938. Lfr: '𝔏',
  939. lfr: '𝔩',
  940. lg: '≶',
  941. lgE: '⪑',
  942. lHar: '⥢',
  943. lhard: '↽',
  944. lharu: '↼',
  945. lharul: '⥪',
  946. lhblk: '▄',
  947. LJcy: 'Љ',
  948. ljcy: 'љ',
  949. llarr: '⇇',
  950. ll: '≪',
  951. Ll: '⋘',
  952. llcorner: '⌞',
  953. Lleftarrow: '⇚',
  954. llhard: '⥫',
  955. lltri: '◺',
  956. Lmidot: 'Ŀ',
  957. lmidot: 'ŀ',
  958. lmoustache: '⎰',
  959. lmoust: '⎰',
  960. lnap: '⪉',
  961. lnapprox: '⪉',
  962. lne: '⪇',
  963. lnE: '≨',
  964. lneq: '⪇',
  965. lneqq: '≨',
  966. lnsim: '⋦',
  967. loang: '⟬',
  968. loarr: '⇽',
  969. lobrk: '⟦',
  970. longleftarrow: '⟵',
  971. LongLeftArrow: '⟵',
  972. Longleftarrow: '⟸',
  973. longleftrightarrow: '⟷',
  974. LongLeftRightArrow: '⟷',
  975. Longleftrightarrow: '⟺',
  976. longmapsto: '⟼',
  977. longrightarrow: '⟶',
  978. LongRightArrow: '⟶',
  979. Longrightarrow: '⟹',
  980. looparrowleft: '↫',
  981. looparrowright: '↬',
  982. lopar: '⦅',
  983. Lopf: '𝕃',
  984. lopf: '𝕝',
  985. loplus: '⨭',
  986. lotimes: '⨴',
  987. lowast: '∗',
  988. lowbar: '_',
  989. LowerLeftArrow: '↙',
  990. LowerRightArrow: '↘',
  991. loz: '◊',
  992. lozenge: '◊',
  993. lozf: '⧫',
  994. lpar: '(',
  995. lparlt: '⦓',
  996. lrarr: '⇆',
  997. lrcorner: '⌟',
  998. lrhar: '⇋',
  999. lrhard: '⥭',
  1000. lrm: '‎',
  1001. lrtri: '⊿',
  1002. lsaquo: '‹',
  1003. lscr: '𝓁',
  1004. Lscr: 'ℒ',
  1005. lsh: '↰',
  1006. Lsh: '↰',
  1007. lsim: '≲',
  1008. lsime: '⪍',
  1009. lsimg: '⪏',
  1010. lsqb: '[',
  1011. lsquo: '‘',
  1012. lsquor: '‚',
  1013. Lstrok: 'Ł',
  1014. lstrok: 'ł',
  1015. ltcc: '⪦',
  1016. ltcir: '⩹',
  1017. lt: '<',
  1018. LT: '<',
  1019. Lt: '≪',
  1020. ltdot: '⋖',
  1021. lthree: '⋋',
  1022. ltimes: '⋉',
  1023. ltlarr: '⥶',
  1024. ltquest: '⩻',
  1025. ltri: '◃',
  1026. ltrie: '⊴',
  1027. ltrif: '◂',
  1028. ltrPar: '⦖',
  1029. lurdshar: '⥊',
  1030. luruhar: '⥦',
  1031. lvertneqq: '≨',
  1032. lvnE: '≨',
  1033. macr: '¯',
  1034. male: '♂',
  1035. malt: '✠',
  1036. maltese: '✠',
  1037. Map: '⤅',
  1038. map: '↦',
  1039. mapsto: '↦',
  1040. mapstodown: '↧',
  1041. mapstoleft: '↤',
  1042. mapstoup: '↥',
  1043. marker: '▮',
  1044. mcomma: '⨩',
  1045. Mcy: 'М',
  1046. mcy: 'м',
  1047. mdash: '—',
  1048. mDDot: '∺',
  1049. measuredangle: '∡',
  1050. MediumSpace: ' ',
  1051. Mellintrf: 'ℳ',
  1052. Mfr: '𝔐',
  1053. mfr: '𝔪',
  1054. mho: '℧',
  1055. micro: 'µ',
  1056. midast: '*',
  1057. midcir: '⫰',
  1058. mid: '∣',
  1059. middot: '·',
  1060. minusb: '⊟',
  1061. minus: '−',
  1062. minusd: '∸',
  1063. minusdu: '⨪',
  1064. MinusPlus: '∓',
  1065. mlcp: '⫛',
  1066. mldr: '…',
  1067. mnplus: '∓',
  1068. models: '⊧',
  1069. Mopf: '𝕄',
  1070. mopf: '𝕞',
  1071. mp: '∓',
  1072. mscr: '𝓂',
  1073. Mscr: 'ℳ',
  1074. mstpos: '∾',
  1075. Mu: 'Μ',
  1076. mu: 'μ',
  1077. multimap: '⊸',
  1078. mumap: '⊸',
  1079. nabla: '∇',
  1080. Nacute: 'Ń',
  1081. nacute: 'ń',
  1082. nang: '∠',
  1083. nap: '≉',
  1084. napE: '⩰',
  1085. napid: '≋',
  1086. napos: 'ʼn',
  1087. napprox: '≉',
  1088. natural: '♮',
  1089. naturals: 'ℕ',
  1090. natur: '♮',
  1091. nbsp: ' ',
  1092. nbump: '≎',
  1093. nbumpe: '≏',
  1094. ncap: '⩃',
  1095. Ncaron: 'Ň',
  1096. ncaron: 'ň',
  1097. Ncedil: 'Ņ',
  1098. ncedil: 'ņ',
  1099. ncong: '≇',
  1100. ncongdot: '⩭',
  1101. ncup: '⩂',
  1102. Ncy: 'Н',
  1103. ncy: 'н',
  1104. ndash: '–',
  1105. nearhk: '⤤',
  1106. nearr: '↗',
  1107. neArr: '⇗',
  1108. nearrow: '↗',
  1109. ne: '≠',
  1110. nedot: '≐',
  1111. NegativeMediumSpace: '​',
  1112. NegativeThickSpace: '​',
  1113. NegativeThinSpace: '​',
  1114. NegativeVeryThinSpace: '​',
  1115. nequiv: '≢',
  1116. nesear: '⤨',
  1117. nesim: '≂',
  1118. NestedGreaterGreater: '≫',
  1119. NestedLessLess: '≪',
  1120. NewLine: '\n',
  1121. nexist: '∄',
  1122. nexists: '∄',
  1123. Nfr: '𝔑',
  1124. nfr: '𝔫',
  1125. ngE: '≧',
  1126. nge: '≱',
  1127. ngeq: '≱',
  1128. ngeqq: '≧',
  1129. ngeqslant: '⩾',
  1130. nges: '⩾',
  1131. nGg: '⋙',
  1132. ngsim: '≵',
  1133. nGt: '≫',
  1134. ngt: '≯',
  1135. ngtr: '≯',
  1136. nGtv: '≫',
  1137. nharr: '↮',
  1138. nhArr: '⇎',
  1139. nhpar: '⫲',
  1140. ni: '∋',
  1141. nis: '⋼',
  1142. nisd: '⋺',
  1143. niv: '∋',
  1144. NJcy: 'Њ',
  1145. njcy: 'њ',
  1146. nlarr: '↚',
  1147. nlArr: '⇍',
  1148. nldr: '‥',
  1149. nlE: '≦',
  1150. nle: '≰',
  1151. nleftarrow: '↚',
  1152. nLeftarrow: '⇍',
  1153. nleftrightarrow: '↮',
  1154. nLeftrightarrow: '⇎',
  1155. nleq: '≰',
  1156. nleqq: '≦',
  1157. nleqslant: '⩽',
  1158. nles: '⩽',
  1159. nless: '≮',
  1160. nLl: '⋘',
  1161. nlsim: '≴',
  1162. nLt: '≪',
  1163. nlt: '≮',
  1164. nltri: '⋪',
  1165. nltrie: '⋬',
  1166. nLtv: '≪',
  1167. nmid: '∤',
  1168. NoBreak: '⁠',
  1169. NonBreakingSpace: ' ',
  1170. nopf: '𝕟',
  1171. Nopf: 'ℕ',
  1172. Not: '⫬',
  1173. not: '¬',
  1174. NotCongruent: '≢',
  1175. NotCupCap: '≭',
  1176. NotDoubleVerticalBar: '∦',
  1177. NotElement: '∉',
  1178. NotEqual: '≠',
  1179. NotEqualTilde: '≂',
  1180. NotExists: '∄',
  1181. NotGreater: '≯',
  1182. NotGreaterEqual: '≱',
  1183. NotGreaterFullEqual: '≧',
  1184. NotGreaterGreater: '≫',
  1185. NotGreaterLess: '≹',
  1186. NotGreaterSlantEqual: '⩾',
  1187. NotGreaterTilde: '≵',
  1188. NotHumpDownHump: '≎',
  1189. NotHumpEqual: '≏',
  1190. notin: '∉',
  1191. notindot: '⋵',
  1192. notinE: '⋹',
  1193. notinva: '∉',
  1194. notinvb: '⋷',
  1195. notinvc: '⋶',
  1196. NotLeftTriangleBar: '⧏',
  1197. NotLeftTriangle: '⋪',
  1198. NotLeftTriangleEqual: '⋬',
  1199. NotLess: '≮',
  1200. NotLessEqual: '≰',
  1201. NotLessGreater: '≸',
  1202. NotLessLess: '≪',
  1203. NotLessSlantEqual: '⩽',
  1204. NotLessTilde: '≴',
  1205. NotNestedGreaterGreater: '⪢',
  1206. NotNestedLessLess: '⪡',
  1207. notni: '∌',
  1208. notniva: '∌',
  1209. notnivb: '⋾',
  1210. notnivc: '⋽',
  1211. NotPrecedes: '⊀',
  1212. NotPrecedesEqual: '⪯',
  1213. NotPrecedesSlantEqual: '⋠',
  1214. NotReverseElement: '∌',
  1215. NotRightTriangleBar: '⧐',
  1216. NotRightTriangle: '⋫',
  1217. NotRightTriangleEqual: '⋭',
  1218. NotSquareSubset: '⊏',
  1219. NotSquareSubsetEqual: '⋢',
  1220. NotSquareSuperset: '⊐',
  1221. NotSquareSupersetEqual: '⋣',
  1222. NotSubset: '⊂',
  1223. NotSubsetEqual: '⊈',
  1224. NotSucceeds: '⊁',
  1225. NotSucceedsEqual: '⪰',
  1226. NotSucceedsSlantEqual: '⋡',
  1227. NotSucceedsTilde: '≿',
  1228. NotSuperset: '⊃',
  1229. NotSupersetEqual: '⊉',
  1230. NotTilde: '≁',
  1231. NotTildeEqual: '≄',
  1232. NotTildeFullEqual: '≇',
  1233. NotTildeTilde: '≉',
  1234. NotVerticalBar: '∤',
  1235. nparallel: '∦',
  1236. npar: '∦',
  1237. nparsl: '⫽',
  1238. npart: '∂',
  1239. npolint: '⨔',
  1240. npr: '⊀',
  1241. nprcue: '⋠',
  1242. nprec: '⊀',
  1243. npreceq: '⪯',
  1244. npre: '⪯',
  1245. nrarrc: '⤳',
  1246. nrarr: '↛',
  1247. nrArr: '⇏',
  1248. nrarrw: '↝',
  1249. nrightarrow: '↛',
  1250. nRightarrow: '⇏',
  1251. nrtri: '⋫',
  1252. nrtrie: '⋭',
  1253. nsc: '⊁',
  1254. nsccue: '⋡',
  1255. nsce: '⪰',
  1256. Nscr: '𝒩',
  1257. nscr: '𝓃',
  1258. nshortmid: '∤',
  1259. nshortparallel: '∦',
  1260. nsim: '≁',
  1261. nsime: '≄',
  1262. nsimeq: '≄',
  1263. nsmid: '∤',
  1264. nspar: '∦',
  1265. nsqsube: '⋢',
  1266. nsqsupe: '⋣',
  1267. nsub: '⊄',
  1268. nsubE: '⫅',
  1269. nsube: '⊈',
  1270. nsubset: '⊂',
  1271. nsubseteq: '⊈',
  1272. nsubseteqq: '⫅',
  1273. nsucc: '⊁',
  1274. nsucceq: '⪰',
  1275. nsup: '⊅',
  1276. nsupE: '⫆',
  1277. nsupe: '⊉',
  1278. nsupset: '⊃',
  1279. nsupseteq: '⊉',
  1280. nsupseteqq: '⫆',
  1281. ntgl: '≹',
  1282. Ntilde: 'Ñ',
  1283. ntilde: 'ñ',
  1284. ntlg: '≸',
  1285. ntriangleleft: '⋪',
  1286. ntrianglelefteq: '⋬',
  1287. ntriangleright: '⋫',
  1288. ntrianglerighteq: '⋭',
  1289. Nu: 'Ν',
  1290. nu: 'ν',
  1291. num: '#',
  1292. numero: '№',
  1293. numsp: ' ',
  1294. nvap: '≍',
  1295. nvdash: '⊬',
  1296. nvDash: '⊭',
  1297. nVdash: '⊮',
  1298. nVDash: '⊯',
  1299. nvge: '≥',
  1300. nvgt: '>',
  1301. nvHarr: '⤄',
  1302. nvinfin: '⧞',
  1303. nvlArr: '⤂',
  1304. nvle: '≤',
  1305. nvlt: '>',
  1306. nvltrie: '⊴',
  1307. nvrArr: '⤃',
  1308. nvrtrie: '⊵',
  1309. nvsim: '∼',
  1310. nwarhk: '⤣',
  1311. nwarr: '↖',
  1312. nwArr: '⇖',
  1313. nwarrow: '↖',
  1314. nwnear: '⤧',
  1315. Oacute: 'Ó',
  1316. oacute: 'ó',
  1317. oast: '⊛',
  1318. Ocirc: 'Ô',
  1319. ocirc: 'ô',
  1320. ocir: '⊚',
  1321. Ocy: 'О',
  1322. ocy: 'о',
  1323. odash: '⊝',
  1324. Odblac: 'Ő',
  1325. odblac: 'ő',
  1326. odiv: '⨸',
  1327. odot: '⊙',
  1328. odsold: '⦼',
  1329. OElig: 'Œ',
  1330. oelig: 'œ',
  1331. ofcir: '⦿',
  1332. Ofr: '𝔒',
  1333. ofr: '𝔬',
  1334. ogon: '˛',
  1335. Ograve: 'Ò',
  1336. ograve: 'ò',
  1337. ogt: '⧁',
  1338. ohbar: '⦵',
  1339. ohm: 'Ω',
  1340. oint: '∮',
  1341. olarr: '↺',
  1342. olcir: '⦾',
  1343. olcross: '⦻',
  1344. oline: '‾',
  1345. olt: '⧀',
  1346. Omacr: 'Ō',
  1347. omacr: 'ō',
  1348. Omega: 'Ω',
  1349. omega: 'ω',
  1350. Omicron: 'Ο',
  1351. omicron: 'ο',
  1352. omid: '⦶',
  1353. ominus: '⊖',
  1354. Oopf: '𝕆',
  1355. oopf: '𝕠',
  1356. opar: '⦷',
  1357. OpenCurlyDoubleQuote: '“',
  1358. OpenCurlyQuote: '‘',
  1359. operp: '⦹',
  1360. oplus: '⊕',
  1361. orarr: '↻',
  1362. Or: '⩔',
  1363. or: '∨',
  1364. ord: '⩝',
  1365. order: 'ℴ',
  1366. orderof: 'ℴ',
  1367. ordf: 'ª',
  1368. ordm: 'º',
  1369. origof: '⊶',
  1370. oror: '⩖',
  1371. orslope: '⩗',
  1372. orv: '⩛',
  1373. oS: 'Ⓢ',
  1374. Oscr: '𝒪',
  1375. oscr: 'ℴ',
  1376. Oslash: 'Ø',
  1377. oslash: 'ø',
  1378. osol: '⊘',
  1379. Otilde: 'Õ',
  1380. otilde: 'õ',
  1381. otimesas: '⨶',
  1382. Otimes: '⨷',
  1383. otimes: '⊗',
  1384. Ouml: 'Ö',
  1385. ouml: 'ö',
  1386. ovbar: '⌽',
  1387. OverBar: '‾',
  1388. OverBrace: '⏞',
  1389. OverBracket: '⎴',
  1390. OverParenthesis: '⏜',
  1391. para: '¶',
  1392. parallel: '∥',
  1393. par: '∥',
  1394. parsim: '⫳',
  1395. parsl: '⫽',
  1396. part: '∂',
  1397. PartialD: '∂',
  1398. Pcy: 'П',
  1399. pcy: 'п',
  1400. percnt: '%',
  1401. period: '.',
  1402. permil: '‰',
  1403. perp: '⊥',
  1404. pertenk: '‱',
  1405. Pfr: '𝔓',
  1406. pfr: '𝔭',
  1407. Phi: 'Φ',
  1408. phi: 'φ',
  1409. phiv: 'ϕ',
  1410. phmmat: 'ℳ',
  1411. phone: '☎',
  1412. Pi: 'Π',
  1413. pi: 'π',
  1414. pitchfork: '⋔',
  1415. piv: 'ϖ',
  1416. planck: 'ℏ',
  1417. planckh: 'ℎ',
  1418. plankv: 'ℏ',
  1419. plusacir: '⨣',
  1420. plusb: '⊞',
  1421. pluscir: '⨢',
  1422. plus: '+',
  1423. plusdo: '∔',
  1424. plusdu: '⨥',
  1425. pluse: '⩲',
  1426. PlusMinus: '±',
  1427. plusmn: '±',
  1428. plussim: '⨦',
  1429. plustwo: '⨧',
  1430. pm: '±',
  1431. Poincareplane: 'ℌ',
  1432. pointint: '⨕',
  1433. popf: '𝕡',
  1434. Popf: 'ℙ',
  1435. pound: '£',
  1436. prap: '⪷',
  1437. Pr: '⪻',
  1438. pr: '≺',
  1439. prcue: '≼',
  1440. precapprox: '⪷',
  1441. prec: '≺',
  1442. preccurlyeq: '≼',
  1443. Precedes: '≺',
  1444. PrecedesEqual: '⪯',
  1445. PrecedesSlantEqual: '≼',
  1446. PrecedesTilde: '≾',
  1447. preceq: '⪯',
  1448. precnapprox: '⪹',
  1449. precneqq: '⪵',
  1450. precnsim: '⋨',
  1451. pre: '⪯',
  1452. prE: '⪳',
  1453. precsim: '≾',
  1454. prime: '′',
  1455. Prime: '″',
  1456. primes: 'ℙ',
  1457. prnap: '⪹',
  1458. prnE: '⪵',
  1459. prnsim: '⋨',
  1460. prod: '∏',
  1461. Product: '∏',
  1462. profalar: '⌮',
  1463. profline: '⌒',
  1464. profsurf: '⌓',
  1465. prop: '∝',
  1466. Proportional: '∝',
  1467. Proportion: '∷',
  1468. propto: '∝',
  1469. prsim: '≾',
  1470. prurel: '⊰',
  1471. Pscr: '𝒫',
  1472. pscr: '𝓅',
  1473. Psi: 'Ψ',
  1474. psi: 'ψ',
  1475. puncsp: ' ',
  1476. Qfr: '𝔔',
  1477. qfr: '𝔮',
  1478. qint: '⨌',
  1479. qopf: '𝕢',
  1480. Qopf: 'ℚ',
  1481. qprime: '⁗',
  1482. Qscr: '𝒬',
  1483. qscr: '𝓆',
  1484. quaternions: 'ℍ',
  1485. quatint: '⨖',
  1486. quest: '?',
  1487. questeq: '≟',
  1488. quot: '"',
  1489. QUOT: '"',
  1490. rAarr: '⇛',
  1491. race: '∽',
  1492. Racute: 'Ŕ',
  1493. racute: 'ŕ',
  1494. radic: '√',
  1495. raemptyv: '⦳',
  1496. rang: '⟩',
  1497. Rang: '⟫',
  1498. rangd: '⦒',
  1499. range: '⦥',
  1500. rangle: '⟩',
  1501. raquo: '»',
  1502. rarrap: '⥵',
  1503. rarrb: '⇥',
  1504. rarrbfs: '⤠',
  1505. rarrc: '⤳',
  1506. rarr: '→',
  1507. Rarr: '↠',
  1508. rArr: '⇒',
  1509. rarrfs: '⤞',
  1510. rarrhk: '↪',
  1511. rarrlp: '↬',
  1512. rarrpl: '⥅',
  1513. rarrsim: '⥴',
  1514. Rarrtl: '⤖',
  1515. rarrtl: '↣',
  1516. rarrw: '↝',
  1517. ratail: '⤚',
  1518. rAtail: '⤜',
  1519. ratio: '∶',
  1520. rationals: 'ℚ',
  1521. rbarr: '⤍',
  1522. rBarr: '⤏',
  1523. RBarr: '⤐',
  1524. rbbrk: '❳',
  1525. rbrace: '}',
  1526. rbrack: ']',
  1527. rbrke: '⦌',
  1528. rbrksld: '⦎',
  1529. rbrkslu: '⦐',
  1530. Rcaron: 'Ř',
  1531. rcaron: 'ř',
  1532. Rcedil: 'Ŗ',
  1533. rcedil: 'ŗ',
  1534. rceil: '⌉',
  1535. rcub: '}',
  1536. Rcy: 'Р',
  1537. rcy: 'р',
  1538. rdca: '⤷',
  1539. rdldhar: '⥩',
  1540. rdquo: '”',
  1541. rdquor: '”',
  1542. rdsh: '↳',
  1543. real: 'ℜ',
  1544. realine: 'ℛ',
  1545. realpart: 'ℜ',
  1546. reals: 'ℝ',
  1547. Re: 'ℜ',
  1548. rect: '▭',
  1549. reg: '®',
  1550. REG: '®',
  1551. ReverseElement: '∋',
  1552. ReverseEquilibrium: '⇋',
  1553. ReverseUpEquilibrium: '⥯',
  1554. rfisht: '⥽',
  1555. rfloor: '⌋',
  1556. rfr: '𝔯',
  1557. Rfr: 'ℜ',
  1558. rHar: '⥤',
  1559. rhard: '⇁',
  1560. rharu: '⇀',
  1561. rharul: '⥬',
  1562. Rho: 'Ρ',
  1563. rho: 'ρ',
  1564. rhov: 'ϱ',
  1565. RightAngleBracket: '⟩',
  1566. RightArrowBar: '⇥',
  1567. rightarrow: '→',
  1568. RightArrow: '→',
  1569. Rightarrow: '⇒',
  1570. RightArrowLeftArrow: '⇄',
  1571. rightarrowtail: '↣',
  1572. RightCeiling: '⌉',
  1573. RightDoubleBracket: '⟧',
  1574. RightDownTeeVector: '⥝',
  1575. RightDownVectorBar: '⥕',
  1576. RightDownVector: '⇂',
  1577. RightFloor: '⌋',
  1578. rightharpoondown: '⇁',
  1579. rightharpoonup: '⇀',
  1580. rightleftarrows: '⇄',
  1581. rightleftharpoons: '⇌',
  1582. rightrightarrows: '⇉',
  1583. rightsquigarrow: '↝',
  1584. RightTeeArrow: '↦',
  1585. RightTee: '⊢',
  1586. RightTeeVector: '⥛',
  1587. rightthreetimes: '⋌',
  1588. RightTriangleBar: '⧐',
  1589. RightTriangle: '⊳',
  1590. RightTriangleEqual: '⊵',
  1591. RightUpDownVector: '⥏',
  1592. RightUpTeeVector: '⥜',
  1593. RightUpVectorBar: '⥔',
  1594. RightUpVector: '↾',
  1595. RightVectorBar: '⥓',
  1596. RightVector: '⇀',
  1597. ring: '˚',
  1598. risingdotseq: '≓',
  1599. rlarr: '⇄',
  1600. rlhar: '⇌',
  1601. rlm: '‏',
  1602. rmoustache: '⎱',
  1603. rmoust: '⎱',
  1604. rnmid: '⫮',
  1605. roang: '⟭',
  1606. roarr: '⇾',
  1607. robrk: '⟧',
  1608. ropar: '⦆',
  1609. ropf: '𝕣',
  1610. Ropf: 'ℝ',
  1611. roplus: '⨮',
  1612. rotimes: '⨵',
  1613. RoundImplies: '⥰',
  1614. rpar: ')',
  1615. rpargt: '⦔',
  1616. rppolint: '⨒',
  1617. rrarr: '⇉',
  1618. Rrightarrow: '⇛',
  1619. rsaquo: '›',
  1620. rscr: '𝓇',
  1621. Rscr: 'ℛ',
  1622. rsh: '↱',
  1623. Rsh: '↱',
  1624. rsqb: ']',
  1625. rsquo: '’',
  1626. rsquor: '’',
  1627. rthree: '⋌',
  1628. rtimes: '⋊',
  1629. rtri: '▹',
  1630. rtrie: '⊵',
  1631. rtrif: '▸',
  1632. rtriltri: '⧎',
  1633. RuleDelayed: '⧴',
  1634. ruluhar: '⥨',
  1635. rx: '℞',
  1636. Sacute: 'Ś',
  1637. sacute: 'ś',
  1638. sbquo: '‚',
  1639. scap: '⪸',
  1640. Scaron: 'Š',
  1641. scaron: 'š',
  1642. Sc: '⪼',
  1643. sc: '≻',
  1644. sccue: '≽',
  1645. sce: '⪰',
  1646. scE: '⪴',
  1647. Scedil: 'Ş',
  1648. scedil: 'ş',
  1649. Scirc: 'Ŝ',
  1650. scirc: 'ŝ',
  1651. scnap: '⪺',
  1652. scnE: '⪶',
  1653. scnsim: '⋩',
  1654. scpolint: '⨓',
  1655. scsim: '≿',
  1656. Scy: 'С',
  1657. scy: 'с',
  1658. sdotb: '⊡',
  1659. sdot: '⋅',
  1660. sdote: '⩦',
  1661. searhk: '⤥',
  1662. searr: '↘',
  1663. seArr: '⇘',
  1664. searrow: '↘',
  1665. sect: '§',
  1666. semi: ';',
  1667. seswar: '⤩',
  1668. setminus: '∖',
  1669. setmn: '∖',
  1670. sext: '✶',
  1671. Sfr: '𝔖',
  1672. sfr: '𝔰',
  1673. sfrown: '⌢',
  1674. sharp: '♯',
  1675. SHCHcy: 'Щ',
  1676. shchcy: 'щ',
  1677. SHcy: 'Ш',
  1678. shcy: 'ш',
  1679. ShortDownArrow: '↓',
  1680. ShortLeftArrow: '←',
  1681. shortmid: '∣',
  1682. shortparallel: '∥',
  1683. ShortRightArrow: '→',
  1684. ShortUpArrow: '↑',
  1685. shy: '­',
  1686. Sigma: 'Σ',
  1687. sigma: 'σ',
  1688. sigmaf: 'ς',
  1689. sigmav: 'ς',
  1690. sim: '∼',
  1691. simdot: '⩪',
  1692. sime: '≃',
  1693. simeq: '≃',
  1694. simg: '⪞',
  1695. simgE: '⪠',
  1696. siml: '⪝',
  1697. simlE: '⪟',
  1698. simne: '≆',
  1699. simplus: '⨤',
  1700. simrarr: '⥲',
  1701. slarr: '←',
  1702. SmallCircle: '∘',
  1703. smallsetminus: '∖',
  1704. smashp: '⨳',
  1705. smeparsl: '⧤',
  1706. smid: '∣',
  1707. smile: '⌣',
  1708. smt: '⪪',
  1709. smte: '⪬',
  1710. smtes: '⪬',
  1711. SOFTcy: 'Ь',
  1712. softcy: 'ь',
  1713. solbar: '⌿',
  1714. solb: '⧄',
  1715. sol: '/',
  1716. Sopf: '𝕊',
  1717. sopf: '𝕤',
  1718. spades: '♠',
  1719. spadesuit: '♠',
  1720. spar: '∥',
  1721. sqcap: '⊓',
  1722. sqcaps: '⊓',
  1723. sqcup: '⊔',
  1724. sqcups: '⊔',
  1725. Sqrt: '√',
  1726. sqsub: '⊏',
  1727. sqsube: '⊑',
  1728. sqsubset: '⊏',
  1729. sqsubseteq: '⊑',
  1730. sqsup: '⊐',
  1731. sqsupe: '⊒',
  1732. sqsupset: '⊐',
  1733. sqsupseteq: '⊒',
  1734. square: '□',
  1735. Square: '□',
  1736. SquareIntersection: '⊓',
  1737. SquareSubset: '⊏',
  1738. SquareSubsetEqual: '⊑',
  1739. SquareSuperset: '⊐',
  1740. SquareSupersetEqual: '⊒',
  1741. SquareUnion: '⊔',
  1742. squarf: '▪',
  1743. squ: '□',
  1744. squf: '▪',
  1745. srarr: '→',
  1746. Sscr: '𝒮',
  1747. sscr: '𝓈',
  1748. ssetmn: '∖',
  1749. ssmile: '⌣',
  1750. sstarf: '⋆',
  1751. Star: '⋆',
  1752. star: '☆',
  1753. starf: '★',
  1754. straightepsilon: 'ϵ',
  1755. straightphi: 'ϕ',
  1756. strns: '¯',
  1757. sub: '⊂',
  1758. Sub: '⋐',
  1759. subdot: '⪽',
  1760. subE: '⫅',
  1761. sube: '⊆',
  1762. subedot: '⫃',
  1763. submult: '⫁',
  1764. subnE: '⫋',
  1765. subne: '⊊',
  1766. subplus: '⪿',
  1767. subrarr: '⥹',
  1768. subset: '⊂',
  1769. Subset: '⋐',
  1770. subseteq: '⊆',
  1771. subseteqq: '⫅',
  1772. SubsetEqual: '⊆',
  1773. subsetneq: '⊊',
  1774. subsetneqq: '⫋',
  1775. subsim: '⫇',
  1776. subsub: '⫕',
  1777. subsup: '⫓',
  1778. succapprox: '⪸',
  1779. succ: '≻',
  1780. succcurlyeq: '≽',
  1781. Succeeds: '≻',
  1782. SucceedsEqual: '⪰',
  1783. SucceedsSlantEqual: '≽',
  1784. SucceedsTilde: '≿',
  1785. succeq: '⪰',
  1786. succnapprox: '⪺',
  1787. succneqq: '⪶',
  1788. succnsim: '⋩',
  1789. succsim: '≿',
  1790. SuchThat: '∋',
  1791. sum: '∑',
  1792. Sum: '∑',
  1793. sung: '♪',
  1794. sup1: '¹',
  1795. sup2: '²',
  1796. sup3: '³',
  1797. sup: '⊃',
  1798. Sup: '⋑',
  1799. supdot: '⪾',
  1800. supdsub: '⫘',
  1801. supE: '⫆',
  1802. supe: '⊇',
  1803. supedot: '⫄',
  1804. Superset: '⊃',
  1805. SupersetEqual: '⊇',
  1806. suphsol: '⟉',
  1807. suphsub: '⫗',
  1808. suplarr: '⥻',
  1809. supmult: '⫂',
  1810. supnE: '⫌',
  1811. supne: '⊋',
  1812. supplus: '⫀',
  1813. supset: '⊃',
  1814. Supset: '⋑',
  1815. supseteq: '⊇',
  1816. supseteqq: '⫆',
  1817. supsetneq: '⊋',
  1818. supsetneqq: '⫌',
  1819. supsim: '⫈',
  1820. supsub: '⫔',
  1821. supsup: '⫖',
  1822. swarhk: '⤦',
  1823. swarr: '↙',
  1824. swArr: '⇙',
  1825. swarrow: '↙',
  1826. swnwar: '⤪',
  1827. szlig: 'ß',
  1828. Tab: ' ',
  1829. target: '⌖',
  1830. Tau: 'Τ',
  1831. tau: 'τ',
  1832. tbrk: '⎴',
  1833. Tcaron: 'Ť',
  1834. tcaron: 'ť',
  1835. Tcedil: 'Ţ',
  1836. tcedil: 'ţ',
  1837. Tcy: 'Т',
  1838. tcy: 'т',
  1839. tdot: '⃛',
  1840. telrec: '⌕',
  1841. Tfr: '𝔗',
  1842. tfr: '𝔱',
  1843. there4: '∴',
  1844. therefore: '∴',
  1845. Therefore: '∴',
  1846. Theta: 'Θ',
  1847. theta: 'θ',
  1848. thetasym: 'ϑ',
  1849. thetav: 'ϑ',
  1850. thickapprox: '≈',
  1851. thicksim: '∼',
  1852. ThickSpace: ' ',
  1853. ThinSpace: ' ',
  1854. thinsp: ' ',
  1855. thkap: '≈',
  1856. thksim: '∼',
  1857. THORN: 'Þ',
  1858. thorn: 'þ',
  1859. tilde: '˜',
  1860. Tilde: '∼',
  1861. TildeEqual: '≃',
  1862. TildeFullEqual: '≅',
  1863. TildeTilde: '≈',
  1864. timesbar: '⨱',
  1865. timesb: '⊠',
  1866. times: '×',
  1867. timesd: '⨰',
  1868. tint: '∭',
  1869. toea: '⤨',
  1870. topbot: '⌶',
  1871. topcir: '⫱',
  1872. top: '⊤',
  1873. Topf: '𝕋',
  1874. topf: '𝕥',
  1875. topfork: '⫚',
  1876. tosa: '⤩',
  1877. tprime: '‴',
  1878. trade: '™',
  1879. TRADE: '™',
  1880. triangle: '▵',
  1881. triangledown: '▿',
  1882. triangleleft: '◃',
  1883. trianglelefteq: '⊴',
  1884. triangleq: '≜',
  1885. triangleright: '▹',
  1886. trianglerighteq: '⊵',
  1887. tridot: '◬',
  1888. trie: '≜',
  1889. triminus: '⨺',
  1890. TripleDot: '⃛',
  1891. triplus: '⨹',
  1892. trisb: '⧍',
  1893. tritime: '⨻',
  1894. trpezium: '⏢',
  1895. Tscr: '𝒯',
  1896. tscr: '𝓉',
  1897. TScy: 'Ц',
  1898. tscy: 'ц',
  1899. TSHcy: 'Ћ',
  1900. tshcy: 'ћ',
  1901. Tstrok: 'Ŧ',
  1902. tstrok: 'ŧ',
  1903. twixt: '≬',
  1904. twoheadleftarrow: '↞',
  1905. twoheadrightarrow: '↠',
  1906. Uacute: 'Ú',
  1907. uacute: 'ú',
  1908. uarr: '↑',
  1909. Uarr: '↟',
  1910. uArr: '⇑',
  1911. Uarrocir: '⥉',
  1912. Ubrcy: 'Ў',
  1913. ubrcy: 'ў',
  1914. Ubreve: 'Ŭ',
  1915. ubreve: 'ŭ',
  1916. Ucirc: 'Û',
  1917. ucirc: 'û',
  1918. Ucy: 'У',
  1919. ucy: 'у',
  1920. udarr: '⇅',
  1921. Udblac: 'Ű',
  1922. udblac: 'ű',
  1923. udhar: '⥮',
  1924. ufisht: '⥾',
  1925. Ufr: '𝔘',
  1926. ufr: '𝔲',
  1927. Ugrave: 'Ù',
  1928. ugrave: 'ù',
  1929. uHar: '⥣',
  1930. uharl: '↿',
  1931. uharr: '↾',
  1932. uhblk: '▀',
  1933. ulcorn: '⌜',
  1934. ulcorner: '⌜',
  1935. ulcrop: '⌏',
  1936. ultri: '◸',
  1937. Umacr: 'Ū',
  1938. umacr: 'ū',
  1939. uml: '¨',
  1940. UnderBar: '_',
  1941. UnderBrace: '⏟',
  1942. UnderBracket: '⎵',
  1943. UnderParenthesis: '⏝',
  1944. Union: '⋃',
  1945. UnionPlus: '⊎',
  1946. Uogon: 'Ų',
  1947. uogon: 'ų',
  1948. Uopf: '𝕌',
  1949. uopf: '𝕦',
  1950. UpArrowBar: '⤒',
  1951. uparrow: '↑',
  1952. UpArrow: '↑',
  1953. Uparrow: '⇑',
  1954. UpArrowDownArrow: '⇅',
  1955. updownarrow: '↕',
  1956. UpDownArrow: '↕',
  1957. Updownarrow: '⇕',
  1958. UpEquilibrium: '⥮',
  1959. upharpoonleft: '↿',
  1960. upharpoonright: '↾',
  1961. uplus: '⊎',
  1962. UpperLeftArrow: '↖',
  1963. UpperRightArrow: '↗',
  1964. upsi: 'υ',
  1965. Upsi: 'ϒ',
  1966. upsih: 'ϒ',
  1967. Upsilon: 'Υ',
  1968. upsilon: 'υ',
  1969. UpTeeArrow: '↥',
  1970. UpTee: '⊥',
  1971. upuparrows: '⇈',
  1972. urcorn: '⌝',
  1973. urcorner: '⌝',
  1974. urcrop: '⌎',
  1975. Uring: 'Ů',
  1976. uring: 'ů',
  1977. urtri: '◹',
  1978. Uscr: '𝒰',
  1979. uscr: '𝓊',
  1980. utdot: '⋰',
  1981. Utilde: 'Ũ',
  1982. utilde: 'ũ',
  1983. utri: '▵',
  1984. utrif: '▴',
  1985. uuarr: '⇈',
  1986. Uuml: 'Ü',
  1987. uuml: 'ü',
  1988. uwangle: '⦧',
  1989. vangrt: '⦜',
  1990. varepsilon: 'ϵ',
  1991. varkappa: 'ϰ',
  1992. varnothing: '∅',
  1993. varphi: 'ϕ',
  1994. varpi: 'ϖ',
  1995. varpropto: '∝',
  1996. varr: '↕',
  1997. vArr: '⇕',
  1998. varrho: 'ϱ',
  1999. varsigma: 'ς',
  2000. varsubsetneq: '⊊',
  2001. varsubsetneqq: '⫋',
  2002. varsupsetneq: '⊋',
  2003. varsupsetneqq: '⫌',
  2004. vartheta: 'ϑ',
  2005. vartriangleleft: '⊲',
  2006. vartriangleright: '⊳',
  2007. vBar: '⫨',
  2008. Vbar: '⫫',
  2009. vBarv: '⫩',
  2010. Vcy: 'В',
  2011. vcy: 'в',
  2012. vdash: '⊢',
  2013. vDash: '⊨',
  2014. Vdash: '⊩',
  2015. VDash: '⊫',
  2016. Vdashl: '⫦',
  2017. veebar: '⊻',
  2018. vee: '∨',
  2019. Vee: '⋁',
  2020. veeeq: '≚',
  2021. vellip: '⋮',
  2022. verbar: '|',
  2023. Verbar: '‖',
  2024. vert: '|',
  2025. Vert: '‖',
  2026. VerticalBar: '∣',
  2027. VerticalLine: '|',
  2028. VerticalSeparator: '❘',
  2029. VerticalTilde: '≀',
  2030. VeryThinSpace: ' ',
  2031. Vfr: '𝔙',
  2032. vfr: '𝔳',
  2033. vltri: '⊲',
  2034. vnsub: '⊂',
  2035. vnsup: '⊃',
  2036. Vopf: '𝕍',
  2037. vopf: '𝕧',
  2038. vprop: '∝',
  2039. vrtri: '⊳',
  2040. Vscr: '𝒱',
  2041. vscr: '𝓋',
  2042. vsubnE: '⫋',
  2043. vsubne: '⊊',
  2044. vsupnE: '⫌',
  2045. vsupne: '⊋',
  2046. Vvdash: '⊪',
  2047. vzigzag: '⦚',
  2048. Wcirc: 'Ŵ',
  2049. wcirc: 'ŵ',
  2050. wedbar: '⩟',
  2051. wedge: '∧',
  2052. Wedge: '⋀',
  2053. wedgeq: '≙',
  2054. weierp: '℘',
  2055. Wfr: '𝔚',
  2056. wfr: '𝔴',
  2057. Wopf: '𝕎',
  2058. wopf: '𝕨',
  2059. wp: '℘',
  2060. wr: '≀',
  2061. wreath: '≀',
  2062. Wscr: '𝒲',
  2063. wscr: '𝓌',
  2064. xcap: '⋂',
  2065. xcirc: '◯',
  2066. xcup: '⋃',
  2067. xdtri: '▽',
  2068. Xfr: '𝔛',
  2069. xfr: '𝔵',
  2070. xharr: '⟷',
  2071. xhArr: '⟺',
  2072. Xi: 'Ξ',
  2073. xi: 'ξ',
  2074. xlarr: '⟵',
  2075. xlArr: '⟸',
  2076. xmap: '⟼',
  2077. xnis: '⋻',
  2078. xodot: '⨀',
  2079. Xopf: '𝕏',
  2080. xopf: '𝕩',
  2081. xoplus: '⨁',
  2082. xotime: '⨂',
  2083. xrarr: '⟶',
  2084. xrArr: '⟹',
  2085. Xscr: '𝒳',
  2086. xscr: '𝓍',
  2087. xsqcup: '⨆',
  2088. xuplus: '⨄',
  2089. xutri: '△',
  2090. xvee: '⋁',
  2091. xwedge: '⋀',
  2092. Yacute: 'Ý',
  2093. yacute: 'ý',
  2094. YAcy: 'Я',
  2095. yacy: 'я',
  2096. Ycirc: 'Ŷ',
  2097. ycirc: 'ŷ',
  2098. Ycy: 'Ы',
  2099. ycy: 'ы',
  2100. yen: '¥',
  2101. Yfr: '𝔜',
  2102. yfr: '𝔶',
  2103. YIcy: 'Ї',
  2104. yicy: 'ї',
  2105. Yopf: '𝕐',
  2106. yopf: '𝕪',
  2107. Yscr: '𝒴',
  2108. yscr: '𝓎',
  2109. YUcy: 'Ю',
  2110. yucy: 'ю',
  2111. yuml: 'ÿ',
  2112. Yuml: 'Ÿ',
  2113. Zacute: 'Ź',
  2114. zacute: 'ź',
  2115. Zcaron: 'Ž',
  2116. zcaron: 'ž',
  2117. Zcy: 'З',
  2118. zcy: 'з',
  2119. Zdot: 'Ż',
  2120. zdot: 'ż',
  2121. zeetrf: 'ℨ',
  2122. ZeroWidthSpace: '​',
  2123. Zeta: 'Ζ',
  2124. zeta: 'ζ',
  2125. zfr: '𝔷',
  2126. Zfr: 'ℨ',
  2127. ZHcy: 'Ж',
  2128. zhcy: 'ж',
  2129. zigrarr: '⇝',
  2130. zopf: '𝕫',
  2131. Zopf: 'ℤ',
  2132. Zscr: '𝒵',
  2133. zscr: '𝓏',
  2134. zwj: '‍',
  2135. zwnj: '‌' };
  2136. // Constants for character codes:
  2137. var C_NEWLINE = 10;
  2138. var C_SPACE = 32;
  2139. var C_ASTERISK = 42;
  2140. var C_UNDERSCORE = 95;
  2141. var C_BACKTICK = 96;
  2142. var C_OPEN_BRACKET = 91;
  2143. var C_CLOSE_BRACKET = 93;
  2144. var C_LESSTHAN = 60;
  2145. var C_GREATERTHAN = 62;
  2146. var C_BANG = 33;
  2147. var C_BACKSLASH = 92;
  2148. var C_AMPERSAND = 38;
  2149. var C_OPEN_PAREN = 40;
  2150. var C_COLON = 58;
  2151. // Some regexps used in inline parser:
  2152. var ESCAPABLE = '[!"#$%&\'()*+,./:;<=>?@[\\\\\\]^_`{|}~-]';
  2153. var ESCAPED_CHAR = '\\\\' + ESCAPABLE;
  2154. var IN_DOUBLE_QUOTES = '"(' + ESCAPED_CHAR + '|[^"\\x00])*"';
  2155. var IN_SINGLE_QUOTES = '\'(' + ESCAPED_CHAR + '|[^\'\\x00])*\'';
  2156. var IN_PARENS = '\\((' + ESCAPED_CHAR + '|[^)\\x00])*\\)';
  2157. var REG_CHAR = '[^\\\\()\\x00-\\x20]';
  2158. var IN_PARENS_NOSP = '\\((' + REG_CHAR + '|' + ESCAPED_CHAR + ')*\\)';
  2159. var TAGNAME = '[A-Za-z][A-Za-z0-9]*';
  2160. var BLOCKTAGNAME = '(?:article|header|aside|hgroup|iframe|blockquote|hr|body|li|map|button|object|canvas|ol|caption|output|col|p|colgroup|pre|dd|progress|div|section|dl|table|td|dt|tbody|embed|textarea|fieldset|tfoot|figcaption|th|figure|thead|footer|footer|tr|form|ul|h1|h2|h3|h4|h5|h6|video|script|style)';
  2161. var ATTRIBUTENAME = '[a-zA-Z_:][a-zA-Z0-9:._-]*';
  2162. var UNQUOTEDVALUE = "[^\"'=<>`\\x00-\\x20]+";
  2163. var SINGLEQUOTEDVALUE = "'[^']*'";
  2164. var DOUBLEQUOTEDVALUE = '"[^"]*"';
  2165. var ATTRIBUTEVALUE = "(?:" + UNQUOTEDVALUE + "|" + SINGLEQUOTEDVALUE + "|" + DOUBLEQUOTEDVALUE + ")";
  2166. var ATTRIBUTEVALUESPEC = "(?:" + "\\s*=" + "\\s*" + ATTRIBUTEVALUE + ")";
  2167. var ATTRIBUTE = "(?:" + "\\s+" + ATTRIBUTENAME + ATTRIBUTEVALUESPEC + "?)";
  2168. var OPENTAG = "<" + TAGNAME + ATTRIBUTE + "*" + "\\s*/?>";
  2169. var CLOSETAG = "</" + TAGNAME + "\\s*[>]";
  2170. var OPENBLOCKTAG = "<" + BLOCKTAGNAME + ATTRIBUTE + "*" + "\\s*/?>";
  2171. var CLOSEBLOCKTAG = "</" + BLOCKTAGNAME + "\\s*[>]";
  2172. var HTMLCOMMENT = "<!--([^-]+|[-][^-]+)*-->";
  2173. var PROCESSINGINSTRUCTION = "[<][?].*?[?][>]";
  2174. var DECLARATION = "<![A-Z]+" + "\\s+[^>]*>";
  2175. var CDATA = "<!\\[CDATA\\[([^\\]]+|\\][^\\]]|\\]\\][^>])*\\]\\]>";
  2176. var HTMLTAG = "(?:" + OPENTAG + "|" + CLOSETAG + "|" + HTMLCOMMENT + "|" +
  2177. PROCESSINGINSTRUCTION + "|" + DECLARATION + "|" + CDATA + ")";
  2178. var HTMLBLOCKOPEN = "<(?:" + BLOCKTAGNAME + "[\\s/>]" + "|" +
  2179. "/" + BLOCKTAGNAME + "[\\s>]" + "|" + "[?!])";
  2180. var ENTITY = "&(?:#x[a-f0-9]{1,8}|#[0-9]{1,8}|[a-z][a-z0-9]{1,31});"
  2181. var reHtmlTag = new RegExp('^' + HTMLTAG, 'i');
  2182. var reHtmlBlockOpen = new RegExp('^' + HTMLBLOCKOPEN, 'i');
  2183. var reLinkTitle = new RegExp(
  2184. '^(?:"(' + ESCAPED_CHAR + '|[^"\\x00])*"' +
  2185. '|' +
  2186. '\'(' + ESCAPED_CHAR + '|[^\'\\x00])*\'' +
  2187. '|' +
  2188. '\\((' + ESCAPED_CHAR + '|[^)\\x00])*\\))');
  2189. var reLinkDestinationBraces = new RegExp(
  2190. '^(?:[<](?:[^<>\\n\\\\\\x00]' + '|' + ESCAPED_CHAR + '|' + '\\\\)*[>])');
  2191. var reLinkDestination = new RegExp(
  2192. '^(?:' + REG_CHAR + '+|' + ESCAPED_CHAR + '|' + IN_PARENS_NOSP + ')*');
  2193. var reEscapable = new RegExp(ESCAPABLE);
  2194. var reAllEscapedChar = new RegExp('\\\\(' + ESCAPABLE + ')', 'g');
  2195. var reEscapedChar = new RegExp('^\\\\(' + ESCAPABLE + ')');
  2196. var reAllTab = /\t/g;
  2197. var reHrule = /^(?:(?:\* *){3,}|(?:_ *){3,}|(?:- *){3,}) *$/;
  2198. var reEntityHere = new RegExp('^' + ENTITY, 'i');
  2199. var reEntity = new RegExp(ENTITY, 'gi');
  2200. // Matches a character with a special meaning in markdown,
  2201. // or a string of non-special characters. Note: we match
  2202. // clumps of _ or * or `, because they need to be handled in groups.
  2203. var reMain = /^(?:[_*`\n]+|[\[\]\\!<&*_]|(?: *[^\n `\[\]\\!<&*_]+)+|[ \n]+)/m;
  2204. // UTILITY FUNCTIONS
  2205. var entityToChar = function(m) {
  2206. var isNumeric = /^&#/.test(m);
  2207. var isHex = /^&#[Xx]/.test(m);
  2208. var uchar;
  2209. if (isNumeric) {
  2210. var num;
  2211. if (isHex) {
  2212. num = parseInt(m.slice(3,-1), 16);
  2213. } else {
  2214. num = parseInt(m.slice(2,-1), 10);
  2215. }
  2216. uchar = String.fromCharCode(num);
  2217. } else {
  2218. uchar = entities[m.slice(1,-1)];
  2219. }
  2220. return (uchar || m);
  2221. }
  2222. // Replace entities and backslash escapes with literal characters.
  2223. var unescapeEntBS = function(s) {
  2224. return s.replace(reAllEscapedChar, '$1')
  2225. .replace(reEntity, entityToChar);;
  2226. };
  2227. // Returns true if string contains only space characters.
  2228. var isBlank = function(s) {
  2229. return /^\s*$/.test(s);
  2230. };
  2231. // Normalize reference label: collapse internal whitespace
  2232. // to single space, remove leading/trailing whitespace, case fold.
  2233. var normalizeReference = function(s) {
  2234. return s.trim()
  2235. .replace(/\s+/,' ')
  2236. .toUpperCase();
  2237. };
  2238. // Attempt to match a regex in string s at offset offset.
  2239. // Return index of match or null.
  2240. var matchAt = function(re, s, offset) {
  2241. var res = s.slice(offset).match(re);
  2242. if (res) {
  2243. return offset + res.index;
  2244. } else {
  2245. return null;
  2246. }
  2247. };
  2248. // Convert tabs to spaces on each line using a 4-space tab stop.
  2249. var detabLine = function(text) {
  2250. if (text.indexOf('\t') == -1) {
  2251. return text;
  2252. } else {
  2253. var lastStop = 0;
  2254. return text.replace(reAllTab, function(match, offset) {
  2255. var result = ' '.slice((offset - lastStop) % 4);
  2256. lastStop = offset + 1;
  2257. return result;
  2258. });
  2259. }
  2260. };
  2261. // INLINE PARSER
  2262. // These are methods of an InlineParser object, defined below.
  2263. // An InlineParser keeps track of a subject (a string to be
  2264. // parsed) and a position in that subject.
  2265. // If re matches at current position in the subject, advance
  2266. // position in subject and return the match; otherwise return null.
  2267. var match = function(re) {
  2268. var match = re.exec(this.subject.slice(this.pos));
  2269. if (match) {
  2270. this.pos += match.index + match[0].length;
  2271. return match[0];
  2272. } else {
  2273. return null;
  2274. }
  2275. };
  2276. // Returns the code for the character at the current subject position, or -1
  2277. // there are no more characters.
  2278. var peek = function() {
  2279. if (this.pos < this.subject.length) {
  2280. return this.subject.charCodeAt(this.pos);
  2281. } else {
  2282. return -1;
  2283. }
  2284. };
  2285. // Parse zero or more space characters, including at most one newline
  2286. var spnl = function() {
  2287. this.match(/^ *(?:\n *)?/);
  2288. return 1;
  2289. };
  2290. // All of the parsers below try to match something at the current position
  2291. // in the subject. If they succeed in matching anything, they
  2292. // return the inline matched, advancing the subject.
  2293. // Attempt to parse backticks, returning either a backtick code span or a
  2294. // literal sequence of backticks.
  2295. var parseBackticks = function(inlines) {
  2296. var startpos = this.pos;
  2297. var ticks = this.match(/^`+/);
  2298. if (!ticks) {
  2299. return 0;
  2300. }
  2301. var afterOpenTicks = this.pos;
  2302. var foundCode = false;
  2303. var match;
  2304. while (!foundCode && (match = this.match(/`+/m))) {
  2305. if (match == ticks) {
  2306. inlines.push({ t: 'Code', c: this.subject.slice(afterOpenTicks,
  2307. this.pos - ticks.length)
  2308. .replace(/[ \n]+/g,' ')
  2309. .trim() });
  2310. return true;
  2311. }
  2312. }
  2313. // If we got here, we didn't match a closing backtick sequence.
  2314. this.pos = afterOpenTicks;
  2315. inlines.push({ t: 'Str', c: ticks });
  2316. return true;
  2317. };
  2318. // Parse a backslash-escaped special character, adding either the escaped
  2319. // character, a hard line break (if the backslash is followed by a newline),
  2320. // or a literal backslash to the 'inlines' list.
  2321. var parseBackslash = function(inlines) {
  2322. var subj = this.subject,
  2323. pos = this.pos;
  2324. if (subj.charCodeAt(pos) === C_BACKSLASH) {
  2325. if (subj.charAt(pos + 1) === '\n') {
  2326. this.pos = this.pos + 2;
  2327. inlines.push({ t: 'Hardbreak' });
  2328. } else if (reEscapable.test(subj.charAt(pos + 1))) {
  2329. this.pos = this.pos + 2;
  2330. inlines.push({ t: 'Str', c: subj.charAt(pos + 1) });
  2331. } else {
  2332. this.pos++;
  2333. inlines.push({t: 'Str', c: '\\'});
  2334. }
  2335. return true;
  2336. } else {
  2337. return false;
  2338. }
  2339. };
  2340. // Attempt to parse an autolink (URL or email in pointy brackets).
  2341. var parseAutolink = function(inlines) {
  2342. var m;
  2343. var dest;
  2344. if ((m = this.match(/^<([a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*)>/))) { // email autolink
  2345. dest = m.slice(1,-1);
  2346. inlines.push(
  2347. {t: 'Link',
  2348. label: [{ t: 'Str', c: dest }],
  2349. destination: 'mailto:' + encodeURI(unescape(dest)) });
  2350. return true;
  2351. } else if ((m = this.match(/^<(?:coap|doi|javascript|aaa|aaas|about|acap|cap|cid|crid|data|dav|dict|dns|file|ftp|geo|go|gopher|h323|http|https|iax|icap|im|imap|info|ipp|iris|iris.beep|iris.xpc|iris.xpcs|iris.lwz|ldap|mailto|mid|msrp|msrps|mtqp|mupdate|news|nfs|ni|nih|nntp|opaquelocktoken|pop|pres|rtsp|service|session|shttp|sieve|sip|sips|sms|snmp|soap.beep|soap.beeps|tag|tel|telnet|tftp|thismessage|tn3270|tip|tv|urn|vemmi|ws|wss|xcon|xcon-userid|xmlrpc.beep|xmlrpc.beeps|xmpp|z39.50r|z39.50s|adiumxtra|afp|afs|aim|apt|attachment|aw|beshare|bitcoin|bolo|callto|chrome|chrome-extension|com-eventbrite-attendee|content|cvs|dlna-playsingle|dlna-playcontainer|dtn|dvb|ed2k|facetime|feed|finger|fish|gg|git|gizmoproject|gtalk|hcp|icon|ipn|irc|irc6|ircs|itms|jar|jms|keyparc|lastfm|ldaps|magnet|maps|market|message|mms|ms-help|msnim|mumble|mvn|notes|oid|palm|paparazzi|platform|proxy|psyc|query|res|resource|rmi|rsync|rtmp|secondlife|sftp|sgn|skype|smb|soldat|spotify|ssh|steam|svn|teamspeak|things|udp|unreal|ut2004|ventrilo|view-source|webcal|wtai|wyciwyg|xfire|xri|ymsgr):[^<>\x00-\x20]*>/i))) {
  2352. dest = m.slice(1,-1);
  2353. inlines.push({
  2354. t: 'Link',
  2355. label: [{ t: 'Str', c: dest }],
  2356. destination: encodeURI(unescape(dest)) });
  2357. return true;
  2358. } else {
  2359. return false;
  2360. }
  2361. };
  2362. // Attempt to parse a raw HTML tag.
  2363. var parseHtmlTag = function(inlines) {
  2364. var m = this.match(reHtmlTag);
  2365. if (m) {
  2366. inlines.push({ t: 'Html', c: m });
  2367. return true;
  2368. } else {
  2369. return false;
  2370. }
  2371. };
  2372. // Scan a sequence of characters with code cc, and return information about
  2373. // the number of delimiters and whether they are positioned such that
  2374. // they can open and/or close emphasis or strong emphasis. A utility
  2375. // function for strong/emph parsing.
  2376. var scanDelims = function(cc) {
  2377. var numdelims = 0;
  2378. var first_close_delims = 0;
  2379. var char_before, char_after, cc_after;
  2380. var startpos = this.pos;
  2381. char_before = this.pos === 0 ? '\n' :
  2382. this.subject.charAt(this.pos - 1);
  2383. while (this.peek() === cc) {
  2384. numdelims++;
  2385. this.pos++;
  2386. }
  2387. cc_after = this.peek();
  2388. if (cc_after === -1) {
  2389. char_after = '\n';
  2390. } else {
  2391. char_after = String.fromCharCode(cc_after);
  2392. }
  2393. var can_open = numdelims > 0 && numdelims <= 3 && !(/\s/.test(char_after));
  2394. var can_close = numdelims > 0 && numdelims <= 3 && !(/\s/.test(char_before));
  2395. if (cc === C_UNDERSCORE) {
  2396. can_open = can_open && !((/[a-z0-9]/i).test(char_before));
  2397. can_close = can_close && !((/[a-z0-9]/i).test(char_after));
  2398. }
  2399. this.pos = startpos;
  2400. return { numdelims: numdelims,
  2401. can_open: can_open,
  2402. can_close: can_close };
  2403. };
  2404. var Emph = function(ils) {
  2405. return {t: 'Emph', c: ils};
  2406. }
  2407. var Strong = function(ils) {
  2408. return {t: 'Strong', c: ils};
  2409. }
  2410. var Str = function(s) {
  2411. return {t: 'Str', c: s};
  2412. }
  2413. // Attempt to parse emphasis or strong emphasis.
  2414. var parseEmphasis = function(cc,inlines) {
  2415. var startpos = this.pos;
  2416. var c ;
  2417. var first_close = 0;
  2418. c = String.fromCharCode(cc);
  2419. var numdelims;
  2420. var numclosedelims;
  2421. var delimpos;
  2422. // Get opening delimiters.
  2423. res = this.scanDelims(cc);
  2424. numdelims = res.numdelims;
  2425. if (numdelims === 0) {
  2426. this.pos = startpos;
  2427. return false;
  2428. }
  2429. if (numdelims >= 4 || !res.can_open) {
  2430. this.pos += numdelims;
  2431. inlines.push(Str(this.subject.slice(startpos, startpos + numdelims)));
  2432. return true;
  2433. }
  2434. this.pos += numdelims;
  2435. var delims_to_match = numdelims;
  2436. var current = [];
  2437. var state = 0;
  2438. var can_close = false;
  2439. var can_open = false;
  2440. var last_emphasis_closer = null;
  2441. while (this.last_emphasis_closer[c] >= this.pos) {
  2442. res = this.scanDelims(cc);
  2443. numclosedelims = res.numdelims;
  2444. if (res.can_close) {
  2445. if (last_emphasis_closer === null ||
  2446. last_emphasis_closer < this.pos) {
  2447. last_emphasis_closer = this.pos;
  2448. }
  2449. if (numclosedelims === 3 && delims_to_match === 3) {
  2450. delims_to_match -= 3;
  2451. this.pos += 3;
  2452. current = [{t: 'Strong', c: [{t: 'Emph', c: current}]}];
  2453. } else if (numclosedelims >= 2 && delims_to_match >= 2) {
  2454. delims_to_match -= 2;
  2455. this.pos += 2;
  2456. current = [{t: 'Strong', c: current}];
  2457. } else if (numclosedelims >= 1 && delims_to_match >= 1) {
  2458. delims_to_match -= 1;
  2459. this.pos += 1;
  2460. current = [{t: 'Emph', c: current}];
  2461. } else {
  2462. if (!(this.parseInline(current,true))) {
  2463. break;
  2464. }
  2465. }
  2466. if (delims_to_match === 0) {
  2467. Array.prototype.push.apply(inlines, current);
  2468. return true;
  2469. }
  2470. } else if (!(this.parseInline(current,true))) {
  2471. break;
  2472. }
  2473. }
  2474. // we didn't match emphasis: fallback
  2475. this.pos = startpos + 1;
  2476. if (last_emphasis_closer) {
  2477. this.last_emphasis_closer[c] = last_emphasis_closer;
  2478. }
  2479. inlines.push(Str(c));
  2480. return true;
  2481. };
  2482. // Attempt to parse link title (sans quotes), returning the string
  2483. // or null if no match.
  2484. var parseLinkTitle = function() {
  2485. var title = this.match(reLinkTitle);
  2486. if (title) {
  2487. // chop off quotes from title and unescape:
  2488. return unescapeEntBS(title.substr(1, title.length - 2));
  2489. } else {
  2490. return null;
  2491. }
  2492. };
  2493. // Attempt to parse link destination, returning the string or
  2494. // null if no match.
  2495. var parseLinkDestination = function() {
  2496. var res = this.match(reLinkDestinationBraces);
  2497. if (res) { // chop off surrounding <..>:
  2498. return encodeURI(unescape(unescapeEntBS(res.substr(1, res.length - 2))));
  2499. } else {
  2500. res = this.match(reLinkDestination);
  2501. if (res !== null) {
  2502. return encodeURI(unescape(unescapeEntBS(res)));
  2503. } else {
  2504. return null;
  2505. }
  2506. }
  2507. };
  2508. // Attempt to parse a link label, returning number of characters parsed.
  2509. var parseLinkLabel = function() {
  2510. if (this.peek() != C_OPEN_BRACKET) {
  2511. return 0;
  2512. }
  2513. var startpos = this.pos;
  2514. var nest_level = 0;
  2515. if (this.label_nest_level > 0) {
  2516. // If we've already checked to the end of this subject
  2517. // for a label, even with a different starting [, we
  2518. // know we won't find one here and we can just return.
  2519. // This avoids lots of backtracking.
  2520. // Note: nest level 1 would be: [foo [bar]
  2521. // nest level 2 would be: [foo [bar [baz]
  2522. this.label_nest_level--;
  2523. return 0;
  2524. }
  2525. this.pos++; // advance past [
  2526. var c;
  2527. while ((c = this.peek()) && c != -1 && (c != C_CLOSE_BRACKET || nest_level > 0)) {
  2528. switch (c) {
  2529. case C_BACKTICK:
  2530. this.parseBackticks([]);
  2531. break;
  2532. case C_LESSTHAN:
  2533. this.parseAutolink([]) || this.parseHtmlTag([]) ||
  2534. this.pos++;
  2535. break;
  2536. case C_OPEN_BRACKET: // nested []
  2537. nest_level++;
  2538. this.pos++;
  2539. break;
  2540. case C_CLOSE_BRACKET: // nested []
  2541. nest_level--;
  2542. this.pos++;
  2543. break;
  2544. case C_BACKSLASH:
  2545. this.parseBackslash([]);
  2546. break;
  2547. default:
  2548. this.parseString([]);
  2549. }
  2550. }
  2551. if (c === C_CLOSE_BRACKET) {
  2552. this.label_nest_level = 0;
  2553. this.pos++; // advance past ]
  2554. return this.pos - startpos;
  2555. } else {
  2556. if (c === -1) {
  2557. this.label_nest_level = nest_level;
  2558. }
  2559. this.pos = startpos;
  2560. return 0;
  2561. }
  2562. };
  2563. // Parse raw link label, including surrounding [], and return
  2564. // inline contents. (Note: this is not a method of InlineParser.)
  2565. var parseRawLabel = function(s) {
  2566. // note: parse without a refmap; we don't want links to resolve
  2567. // in nested brackets!
  2568. return new InlineParser().parse(s.substr(1, s.length - 2), {});
  2569. };
  2570. // Attempt to parse a link. If successful, return the link.
  2571. var parseLink = function(inlines) {
  2572. var startpos = this.pos;
  2573. var reflabel;
  2574. var n;
  2575. var dest;
  2576. var title;
  2577. n = this.parseLinkLabel();
  2578. if (n === 0) {
  2579. return false;
  2580. }
  2581. var afterlabel = this.pos;
  2582. var rawlabel = this.subject.substr(startpos, n);
  2583. // if we got this far, we've parsed a label.
  2584. // Try to parse an explicit link: [label](url "title")
  2585. if (this.peek() == C_OPEN_PAREN) {
  2586. this.pos++;
  2587. if (this.spnl() &&
  2588. ((dest = this.parseLinkDestination()) !== null) &&
  2589. this.spnl() &&
  2590. // make sure there's a space before the title:
  2591. (/^\s/.test(this.subject.charAt(this.pos - 1)) &&
  2592. (title = this.parseLinkTitle() || '') || true) &&
  2593. this.spnl() &&
  2594. this.match(/^\)/)) {
  2595. inlines.push({ t: 'Link',
  2596. destination: dest,
  2597. title: title,
  2598. label: parseRawLabel(rawlabel) });
  2599. return true;
  2600. } else {
  2601. this.pos = startpos;
  2602. return false;
  2603. }
  2604. }
  2605. // If we're here, it wasn't an explicit link. Try to parse a reference link.
  2606. // first, see if there's another label
  2607. var savepos = this.pos;
  2608. this.spnl();
  2609. var beforelabel = this.pos;
  2610. n = this.parseLinkLabel();
  2611. if (n == 2) {
  2612. // empty second label
  2613. reflabel = rawlabel;
  2614. } else if (n > 0) {
  2615. reflabel = this.subject.slice(beforelabel, beforelabel + n);
  2616. } else {
  2617. this.pos = savepos;
  2618. reflabel = rawlabel;
  2619. }
  2620. // lookup rawlabel in refmap
  2621. var link = this.refmap[normalizeReference(reflabel)];
  2622. if (link) {
  2623. inlines.push({t: 'Link',
  2624. destination: link.destination,
  2625. title: link.title,
  2626. label: parseRawLabel(rawlabel) });
  2627. return true;
  2628. } else {
  2629. this.pos = startpos;
  2630. return false;
  2631. }
  2632. // Nothing worked, rewind:
  2633. this.pos = startpos;
  2634. return false;
  2635. };
  2636. // Attempt to parse an entity, return Entity object if successful.
  2637. var parseEntity = function(inlines) {
  2638. var m;
  2639. if ((m = this.match(reEntityHere))) {
  2640. inlines.push({ t: 'Str', c: entityToChar(m) });
  2641. return true;
  2642. } else {
  2643. return false;
  2644. }
  2645. };
  2646. // Parse a run of ordinary characters, or a single character with
  2647. // a special meaning in markdown, as a plain string, adding to inlines.
  2648. var parseString = function(inlines) {
  2649. var m;
  2650. if ((m = this.match(reMain))) {
  2651. inlines.push({ t: 'Str', c: m });
  2652. return true;
  2653. } else {
  2654. return false;
  2655. }
  2656. };
  2657. // Parse a newline. If it was preceded by two spaces, return a hard
  2658. // line break; otherwise a soft line break.
  2659. var parseNewline = function(inlines) {
  2660. var m = this.match(/^ *\n/);
  2661. if (m) {
  2662. if (m.length > 2) {
  2663. inlines.push({ t: 'Hardbreak' });
  2664. } else if (m.length > 0) {
  2665. inlines.push({ t: 'Softbreak' });
  2666. }
  2667. return true;
  2668. }
  2669. return false;
  2670. };
  2671. // Attempt to parse an image. If the opening '!' is not followed
  2672. // by a link, return a literal '!'.
  2673. var parseImage = function(inlines) {
  2674. if (this.match(/^!/)) {
  2675. var link = this.parseLink(inlines);
  2676. if (link) {
  2677. inlines[inlines.length - 1].t = 'Image';
  2678. return true;
  2679. } else {
  2680. inlines.push({ t: 'Str', c: '!' });
  2681. return true;
  2682. }
  2683. } else {
  2684. return false;
  2685. }
  2686. };
  2687. // Attempt to parse a link reference, modifying refmap.
  2688. var parseReference = function(s, refmap) {
  2689. this.subject = s;
  2690. this.pos = 0;
  2691. var rawlabel;
  2692. var dest;
  2693. var title;
  2694. var matchChars;
  2695. var startpos = this.pos;
  2696. var match;
  2697. // label:
  2698. matchChars = this.parseLinkLabel();
  2699. if (matchChars === 0) {
  2700. return 0;
  2701. } else {
  2702. rawlabel = this.subject.substr(0, matchChars);
  2703. }
  2704. // colon:
  2705. if (this.peek() === C_COLON) {
  2706. this.pos++;
  2707. } else {
  2708. this.pos = startpos;
  2709. return 0;
  2710. }
  2711. // link url
  2712. this.spnl();
  2713. dest = this.parseLinkDestination();
  2714. if (dest === null || dest.length === 0) {
  2715. this.pos = startpos;
  2716. return 0;
  2717. }
  2718. var beforetitle = this.pos;
  2719. this.spnl();
  2720. title = this.parseLinkTitle();
  2721. if (title === null) {
  2722. title = '';
  2723. // rewind before spaces
  2724. this.pos = beforetitle;
  2725. }
  2726. // make sure we're at line end:
  2727. if (this.match(/^ *(?:\n|$)/) === null) {
  2728. this.pos = startpos;
  2729. return 0;
  2730. }
  2731. var normlabel = normalizeReference(rawlabel);
  2732. if (!refmap[normlabel]) {
  2733. refmap[normlabel] = { destination: dest, title: title };
  2734. }
  2735. return this.pos - startpos;
  2736. };
  2737. // Parse the next inline element in subject, advancing subject position.
  2738. // If memoize is set, memoize the result.
  2739. // On success, add the result to the inlines list, and return true.
  2740. // On failure, return false.
  2741. var parseInline = function(inlines, memoize) {
  2742. var startpos = this.pos;
  2743. var origlen = inlines.length;
  2744. var memoized = memoize && this.memo[startpos];
  2745. if (memoized) {
  2746. this.pos = memoized.endpos;
  2747. Array.prototype.push.apply(inlines, memoized.inline);
  2748. return true;
  2749. }
  2750. var c = this.peek();
  2751. if (c === -1) {
  2752. return false;
  2753. }
  2754. var res;
  2755. switch(c) {
  2756. case C_NEWLINE:
  2757. case C_SPACE:
  2758. res = this.parseNewline(inlines);
  2759. break;
  2760. case C_BACKSLASH:
  2761. res = this.parseBackslash(inlines);
  2762. break;
  2763. case C_BACKTICK:
  2764. res = this.parseBackticks(inlines);
  2765. break;
  2766. case C_ASTERISK:
  2767. case C_UNDERSCORE:
  2768. res = this.parseEmphasis(c, inlines);
  2769. break;
  2770. case C_OPEN_BRACKET:
  2771. res = this.parseLink(inlines);
  2772. break;
  2773. case C_BANG:
  2774. res = this.parseImage(inlines);
  2775. break;
  2776. case C_LESSTHAN:
  2777. res = this.parseAutolink(inlines) || this.parseHtmlTag(inlines);
  2778. break;
  2779. case C_AMPERSAND:
  2780. res = this.parseEntity(inlines);
  2781. break;
  2782. default:
  2783. res = this.parseString(inlines);
  2784. break;
  2785. }
  2786. if (!res) {
  2787. this.pos += 1;
  2788. inlines.push({t: 'Str', c: String.fromCharCode(c)});
  2789. }
  2790. if (memoize) {
  2791. this.memo[startpos] = { inline: inlines.slice(origlen),
  2792. endpos: this.pos };
  2793. }
  2794. return true;
  2795. };
  2796. // Parse s as a list of inlines, using refmap to resolve references.
  2797. var parseInlines = function(s, refmap) {
  2798. this.subject = s;
  2799. this.pos = 0;
  2800. this.refmap = refmap || {};
  2801. this.memo = {};
  2802. this.last_emphasis_closer = { '*': s.length, '_': s.length };
  2803. var inlines = [];
  2804. while (this.parseInline(inlines, false)) {
  2805. }
  2806. return inlines;
  2807. };
  2808. // The InlineParser object.
  2809. function InlineParser(){
  2810. return {
  2811. subject: '',
  2812. label_nest_level: 0, // used by parseLinkLabel method
  2813. last_emphasis_closer: null, // used by parseEmphasis method
  2814. pos: 0,
  2815. refmap: {},
  2816. memo: {},
  2817. match: match,
  2818. peek: peek,
  2819. spnl: spnl,
  2820. parseBackticks: parseBackticks,
  2821. parseBackslash: parseBackslash,
  2822. parseAutolink: parseAutolink,
  2823. parseHtmlTag: parseHtmlTag,
  2824. scanDelims: scanDelims,
  2825. parseEmphasis: parseEmphasis,
  2826. parseLinkTitle: parseLinkTitle,
  2827. parseLinkDestination: parseLinkDestination,
  2828. parseLinkLabel: parseLinkLabel,
  2829. parseLink: parseLink,
  2830. parseEntity: parseEntity,
  2831. parseString: parseString,
  2832. parseNewline: parseNewline,
  2833. parseImage: parseImage,
  2834. parseReference: parseReference,
  2835. parseInline: parseInline,
  2836. parse: parseInlines
  2837. };
  2838. }
  2839. // DOC PARSER
  2840. // These are methods of a DocParser object, defined below.
  2841. var makeBlock = function(tag, start_line, start_column) {
  2842. return { t: tag,
  2843. open: true,
  2844. last_line_blank: false,
  2845. start_line: start_line,
  2846. start_column: start_column,
  2847. end_line: start_line,
  2848. children: [],
  2849. parent: null,
  2850. // string_content is formed by concatenating strings, in finalize:
  2851. string_content: "",
  2852. strings: [],
  2853. inline_content: []
  2854. };
  2855. };
  2856. // Returns true if parent block can contain child block.
  2857. var canContain = function(parent_type, child_type) {
  2858. return ( parent_type == 'Document' ||
  2859. parent_type == 'BlockQuote' ||
  2860. parent_type == 'ListItem' ||
  2861. (parent_type == 'List' && child_type == 'ListItem') );
  2862. };
  2863. // Returns true if block type can accept lines of text.
  2864. var acceptsLines = function(block_type) {
  2865. return ( block_type == 'Paragraph' ||
  2866. block_type == 'IndentedCode' ||
  2867. block_type == 'FencedCode' );
  2868. };
  2869. // Returns true if block ends with a blank line, descending if needed
  2870. // into lists and sublists.
  2871. var endsWithBlankLine = function(block) {
  2872. if (block.last_line_blank) {
  2873. return true;
  2874. }
  2875. if ((block.t == 'List' || block.t == 'ListItem') && block.children.length > 0) {
  2876. return endsWithBlankLine(block.children[block.children.length - 1]);
  2877. } else {
  2878. return false;
  2879. }
  2880. };
  2881. // Break out of all containing lists, resetting the tip of the
  2882. // document to the parent of the highest list, and finalizing
  2883. // all the lists. (This is used to implement the "two blank lines
  2884. // break of of all lists" feature.)
  2885. var breakOutOfLists = function(block, line_number) {
  2886. var b = block;
  2887. var last_list = null;
  2888. do {
  2889. if (b.t === 'List') {
  2890. last_list = b;
  2891. }
  2892. b = b.parent;
  2893. } while (b);
  2894. if (last_list) {
  2895. while (block != last_list) {
  2896. this.finalize(block, line_number);
  2897. block = block.parent;
  2898. }
  2899. this.finalize(last_list, line_number);
  2900. this.tip = last_list.parent;
  2901. }
  2902. };
  2903. // Add a line to the block at the tip. We assume the tip
  2904. // can accept lines -- that check should be done before calling this.
  2905. var addLine = function(ln, offset) {
  2906. var s = ln.slice(offset);
  2907. if (!(this.tip.open)) {
  2908. throw({ msg: "Attempted to add line (" + ln + ") to closed container." });
  2909. }
  2910. this.tip.strings.push(s);
  2911. };
  2912. // Add block of type tag as a child of the tip. If the tip can't
  2913. // accept children, close and finalize it and try its parent,
  2914. // and so on til we find a block that can accept children.
  2915. var addChild = function(tag, line_number, offset) {
  2916. while (!canContain(this.tip.t, tag)) {
  2917. this.finalize(this.tip, line_number);
  2918. }
  2919. var column_number = offset + 1; // offset 0 = column 1
  2920. var newBlock = makeBlock(tag, line_number, column_number);
  2921. this.tip.children.push(newBlock);
  2922. newBlock.parent = this.tip;
  2923. this.tip = newBlock;
  2924. return newBlock;
  2925. };
  2926. // Parse a list marker and return data on the marker (type,
  2927. // start, delimiter, bullet character, padding) or null.
  2928. var parseListMarker = function(ln, offset) {
  2929. var rest = ln.slice(offset);
  2930. var match;
  2931. var spaces_after_marker;
  2932. var data = {};
  2933. if (rest.match(reHrule)) {
  2934. return null;
  2935. }
  2936. if ((match = rest.match(/^[*+-]( +|$)/))) {
  2937. spaces_after_marker = match[1].length;
  2938. data.type = 'Bullet';
  2939. data.bullet_char = match[0][0];
  2940. } else if ((match = rest.match(/^(\d+)([.)])( +|$)/))) {
  2941. spaces_after_marker = match[3].length;
  2942. data.type = 'Ordered';
  2943. data.start = parseInt(match[1]);
  2944. data.delimiter = match[2];
  2945. } else {
  2946. return null;
  2947. }
  2948. var blank_item = match[0].length === rest.length;
  2949. if (spaces_after_marker >= 5 ||
  2950. spaces_after_marker < 1 ||
  2951. blank_item) {
  2952. data.padding = match[0].length - spaces_after_marker + 1;
  2953. } else {
  2954. data.padding = match[0].length;
  2955. }
  2956. return data;
  2957. };
  2958. // Returns true if the two list items are of the same type,
  2959. // with the same delimiter and bullet character. This is used
  2960. // in agglomerating list items into lists.
  2961. var listsMatch = function(list_data, item_data) {
  2962. return (list_data.type === item_data.type &&
  2963. list_data.delimiter === item_data.delimiter &&
  2964. list_data.bullet_char === item_data.bullet_char);
  2965. };
  2966. // Analyze a line of text and update the document appropriately.
  2967. // We parse markdown text by calling this on each line of input,
  2968. // then finalizing the document.
  2969. var incorporateLine = function(ln, line_number) {
  2970. var all_matched = true;
  2971. var last_child;
  2972. var first_nonspace;
  2973. var offset = 0;
  2974. var match;
  2975. var data;
  2976. var blank;
  2977. var indent;
  2978. var last_matched_container;
  2979. var i;
  2980. var CODE_INDENT = 4;
  2981. var container = this.doc;
  2982. var oldtip = this.tip;
  2983. // Convert tabs to spaces:
  2984. ln = detabLine(ln);
  2985. // For each containing block, try to parse the associated line start.
  2986. // Bail out on failure: container will point to the last matching block.
  2987. // Set all_matched to false if not all containers match.
  2988. while (container.children.length > 0) {
  2989. last_child = container.children[container.children.length - 1];
  2990. if (!last_child.open) {
  2991. break;
  2992. }
  2993. container = last_child;
  2994. match = matchAt(/[^ ]/, ln, offset);
  2995. if (match === null) {
  2996. first_nonspace = ln.length;
  2997. blank = true;
  2998. } else {
  2999. first_nonspace = match;
  3000. blank = false;
  3001. }
  3002. indent = first_nonspace - offset;
  3003. switch (container.t) {
  3004. case 'BlockQuote':
  3005. if (indent <= 3 && ln.charCodeAt(first_nonspace) === C_GREATERTHAN) {
  3006. offset = first_nonspace + 1;
  3007. if (ln.charCodeAt(offset) === C_SPACE) {
  3008. offset++;
  3009. }
  3010. } else {
  3011. all_matched = false;
  3012. }
  3013. break;
  3014. case 'ListItem':
  3015. if (indent >= container.list_data.marker_offset +
  3016. container.list_data.padding) {
  3017. offset += container.list_data.marker_offset +
  3018. container.list_data.padding;
  3019. } else if (blank) {
  3020. offset = first_nonspace;
  3021. } else {
  3022. all_matched = false;
  3023. }
  3024. break;
  3025. case 'IndentedCode':
  3026. if (indent >= CODE_INDENT) {
  3027. offset += CODE_INDENT;
  3028. } else if (blank) {
  3029. offset = first_nonspace;
  3030. } else {
  3031. all_matched = false;
  3032. }
  3033. break;
  3034. case 'ATXHeader':
  3035. case 'SetextHeader':
  3036. case 'HorizontalRule':
  3037. // a header can never container > 1 line, so fail to match:
  3038. all_matched = false;
  3039. break;
  3040. case 'FencedCode':
  3041. // skip optional spaces of fence offset
  3042. i = container.fence_offset;
  3043. while (i > 0 && ln.charCodeAt(offset) === C_SPACE) {
  3044. offset++;
  3045. i--;
  3046. }
  3047. break;
  3048. case 'HtmlBlock':
  3049. if (blank) {
  3050. all_matched = false;
  3051. }
  3052. break;
  3053. case 'Paragraph':
  3054. if (blank) {
  3055. container.last_line_blank = true;
  3056. all_matched = false;
  3057. }
  3058. break;
  3059. default:
  3060. }
  3061. if (!all_matched) {
  3062. container = container.parent; // back up to last matching block
  3063. break;
  3064. }
  3065. }
  3066. last_matched_container = container;
  3067. // This function is used to finalize and close any unmatched
  3068. // blocks. We aren't ready to do this now, because we might
  3069. // have a lazy paragraph continuation, in which case we don't
  3070. // want to close unmatched blocks. So we store this closure for
  3071. // use later, when we have more information.
  3072. var closeUnmatchedBlocks = function(mythis) {
  3073. // finalize any blocks not matched
  3074. while (!already_done && oldtip != last_matched_container) {
  3075. mythis.finalize(oldtip, line_number);
  3076. oldtip = oldtip.parent;
  3077. }
  3078. var already_done = true;
  3079. };
  3080. // Check to see if we've hit 2nd blank line; if so break out of list:
  3081. if (blank && container.last_line_blank) {
  3082. this.breakOutOfLists(container, line_number);
  3083. }
  3084. // Unless last matched container is a code block, try new container starts,
  3085. // adding children to the last matched container:
  3086. while (container.t != 'FencedCode' &&
  3087. container.t != 'IndentedCode' &&
  3088. container.t != 'HtmlBlock' &&
  3089. // this is a little performance optimization:
  3090. matchAt(/^[ #`~*+_=<>0-9-]/,ln,offset) !== null) {
  3091. match = matchAt(/[^ ]/, ln, offset);
  3092. if (match === null) {
  3093. first_nonspace = ln.length;
  3094. blank = true;
  3095. } else {
  3096. first_nonspace = match;
  3097. blank = false;
  3098. }
  3099. indent = first_nonspace - offset;
  3100. if (indent >= CODE_INDENT) {
  3101. // indented code
  3102. if (this.tip.t != 'Paragraph' && !blank) {
  3103. offset += CODE_INDENT;
  3104. closeUnmatchedBlocks(this);
  3105. container = this.addChild('IndentedCode', line_number, offset);
  3106. } else { // indent > 4 in a lazy paragraph continuation
  3107. break;
  3108. }
  3109. } else if (ln.charCodeAt(first_nonspace) === C_GREATERTHAN) {
  3110. // blockquote
  3111. offset = first_nonspace + 1;
  3112. // optional following space
  3113. if (ln.charCodeAt(offset) === C_SPACE) {
  3114. offset++;
  3115. }
  3116. closeUnmatchedBlocks(this);
  3117. container = this.addChild('BlockQuote', line_number, offset);
  3118. } else if ((match = ln.slice(first_nonspace).match(/^#{1,6}(?: +|$)/))) {
  3119. // ATX header
  3120. offset = first_nonspace + match[0].length;
  3121. closeUnmatchedBlocks(this);
  3122. container = this.addChild('ATXHeader', line_number, first_nonspace);
  3123. container.level = match[0].trim().length; // number of #s
  3124. // remove trailing ###s:
  3125. container.strings =
  3126. [ln.slice(offset).replace(/(?:(\\#) *#*| *#+) *$/,'$1')];
  3127. break;
  3128. } else if ((match = ln.slice(first_nonspace).match(/^`{3,}(?!.*`)|^~{3,}(?!.*~)/))) {
  3129. // fenced code block
  3130. var fence_length = match[0].length;
  3131. closeUnmatchedBlocks(this);
  3132. container = this.addChild('FencedCode', line_number, first_nonspace);
  3133. container.fence_length = fence_length;
  3134. container.fence_char = match[0][0];
  3135. container.fence_offset = first_nonspace - offset;
  3136. offset = first_nonspace + fence_length;
  3137. break;
  3138. } else if (matchAt(reHtmlBlockOpen, ln, first_nonspace) !== null) {
  3139. // html block
  3140. closeUnmatchedBlocks(this);
  3141. container = this.addChild('HtmlBlock', line_number, first_nonspace);
  3142. // note, we don't adjust offset because the tag is part of the text
  3143. break;
  3144. } else if (container.t == 'Paragraph' &&
  3145. container.strings.length === 1 &&
  3146. ((match = ln.slice(first_nonspace).match(/^(?:=+|-+) *$/)))) {
  3147. // setext header line
  3148. closeUnmatchedBlocks(this);
  3149. container.t = 'SetextHeader'; // convert Paragraph to SetextHeader
  3150. container.level = match[0][0] === '=' ? 1 : 2;
  3151. offset = ln.length;
  3152. } else if (matchAt(reHrule, ln, first_nonspace) !== null) {
  3153. // hrule
  3154. closeUnmatchedBlocks(this);
  3155. container = this.addChild('HorizontalRule', line_number, first_nonspace);
  3156. offset = ln.length - 1;
  3157. break;
  3158. } else if ((data = parseListMarker(ln, first_nonspace))) {
  3159. // list item
  3160. closeUnmatchedBlocks(this);
  3161. data.marker_offset = indent;
  3162. offset = first_nonspace + data.padding;
  3163. // add the list if needed
  3164. if (container.t !== 'List' ||
  3165. !(listsMatch(container.list_data, data))) {
  3166. container = this.addChild('List', line_number, first_nonspace);
  3167. container.list_data = data;
  3168. }
  3169. // add the list item
  3170. container = this.addChild('ListItem', line_number, first_nonspace);
  3171. container.list_data = data;
  3172. } else {
  3173. break;
  3174. }
  3175. if (acceptsLines(container.t)) {
  3176. // if it's a line container, it can't contain other containers
  3177. break;
  3178. }
  3179. }
  3180. // What remains at the offset is a text line. Add the text to the
  3181. // appropriate container.
  3182. match = matchAt(/[^ ]/, ln, offset);
  3183. if (match === null) {
  3184. first_nonspace = ln.length;
  3185. blank = true;
  3186. } else {
  3187. first_nonspace = match;
  3188. blank = false;
  3189. }
  3190. indent = first_nonspace - offset;
  3191. // First check for a lazy paragraph continuation:
  3192. if (this.tip !== last_matched_container &&
  3193. !blank &&
  3194. this.tip.t == 'Paragraph' &&
  3195. this.tip.strings.length > 0) {
  3196. // lazy paragraph continuation
  3197. this.last_line_blank = false;
  3198. this.addLine(ln, offset);
  3199. } else { // not a lazy continuation
  3200. // finalize any blocks not matched
  3201. closeUnmatchedBlocks(this);
  3202. // Block quote lines are never blank as they start with >
  3203. // and we don't count blanks in fenced code for purposes of tight/loose
  3204. // lists or breaking out of lists. We also don't set last_line_blank
  3205. // on an empty list item.
  3206. container.last_line_blank = blank &&
  3207. !(container.t == 'BlockQuote' ||
  3208. container.t == 'FencedCode' ||
  3209. (container.t == 'ListItem' &&
  3210. container.children.length === 0 &&
  3211. container.start_line == line_number));
  3212. var cont = container;
  3213. while (cont.parent) {
  3214. cont.parent.last_line_blank = false;
  3215. cont = cont.parent;
  3216. }
  3217. switch (container.t) {
  3218. case 'IndentedCode':
  3219. case 'HtmlBlock':
  3220. this.addLine(ln, offset);
  3221. break;
  3222. case 'FencedCode':
  3223. // check for closing code fence:
  3224. match = (indent <= 3 &&
  3225. ln.charAt(first_nonspace) == container.fence_char &&
  3226. ln.slice(first_nonspace).match(/^(?:`{3,}|~{3,})(?= *$)/));
  3227. if (match && match[0].length >= container.fence_length) {
  3228. // don't add closing fence to container; instead, close it:
  3229. this.finalize(container, line_number);
  3230. } else {
  3231. this.addLine(ln, offset);
  3232. }
  3233. break;
  3234. case 'ATXHeader':
  3235. case 'SetextHeader':
  3236. case 'HorizontalRule':
  3237. // nothing to do; we already added the contents.
  3238. break;
  3239. default:
  3240. if (acceptsLines(container.t)) {
  3241. this.addLine(ln, first_nonspace);
  3242. } else if (blank) {
  3243. // do nothing
  3244. } else if (container.t != 'HorizontalRule' &&
  3245. container.t != 'SetextHeader') {
  3246. // create paragraph container for line
  3247. container = this.addChild('Paragraph', line_number, first_nonspace);
  3248. this.addLine(ln, first_nonspace);
  3249. } else {
  3250. console.log("Line " + line_number.toString() +
  3251. " with container type " + container.t +
  3252. " did not match any condition.");
  3253. }
  3254. }
  3255. }
  3256. };
  3257. // Finalize a block. Close it and do any necessary postprocessing,
  3258. // e.g. creating string_content from strings, setting the 'tight'
  3259. // or 'loose' status of a list, and parsing the beginnings
  3260. // of paragraphs for reference definitions. Reset the tip to the
  3261. // parent of the closed block.
  3262. var finalize = function(block, line_number) {
  3263. var pos;
  3264. // don't do anything if the block is already closed
  3265. if (!block.open) {
  3266. return 0;
  3267. }
  3268. block.open = false;
  3269. if (line_number > block.start_line) {
  3270. block.end_line = line_number - 1;
  3271. } else {
  3272. block.end_line = line_number;
  3273. }
  3274. switch (block.t) {
  3275. case 'Paragraph':
  3276. block.string_content = block.strings.join('\n').replace(/^ */m,'');
  3277. // try parsing the beginning as link reference definitions:
  3278. while (block.string_content.charCodeAt(0) === C_OPEN_BRACKET &&
  3279. (pos = this.inlineParser.parseReference(block.string_content,
  3280. this.refmap))) {
  3281. block.string_content = block.string_content.slice(pos);
  3282. if (isBlank(block.string_content)) {
  3283. block.t = 'ReferenceDef';
  3284. break;
  3285. }
  3286. }
  3287. break;
  3288. case 'ATXHeader':
  3289. case 'SetextHeader':
  3290. case 'HtmlBlock':
  3291. block.string_content = block.strings.join('\n');
  3292. break;
  3293. case 'IndentedCode':
  3294. block.string_content = block.strings.join('\n').replace(/(\n *)*$/,'\n');
  3295. break;
  3296. case 'FencedCode':
  3297. // first line becomes info string
  3298. block.info = unescapeEntBS(block.strings[0].trim());
  3299. if (block.strings.length == 1) {
  3300. block.string_content = '';
  3301. } else {
  3302. block.string_content = block.strings.slice(1).join('\n') + '\n';
  3303. }
  3304. break;
  3305. case 'List':
  3306. block.tight = true; // tight by default
  3307. var numitems = block.children.length;
  3308. var i = 0;
  3309. while (i < numitems) {
  3310. var item = block.children[i];
  3311. // check for non-final list item ending with blank line:
  3312. var last_item = i == numitems - 1;
  3313. if (endsWithBlankLine(item) && !last_item) {
  3314. block.tight = false;
  3315. break;
  3316. }
  3317. // recurse into children of list item, to see if there are
  3318. // spaces between any of them:
  3319. var numsubitems = item.children.length;
  3320. var j = 0;
  3321. while (j < numsubitems) {
  3322. var subitem = item.children[j];
  3323. var last_subitem = j == numsubitems - 1;
  3324. if (endsWithBlankLine(subitem) && !(last_item && last_subitem)) {
  3325. block.tight = false;
  3326. break;
  3327. }
  3328. j++;
  3329. }
  3330. i++;
  3331. }
  3332. break;
  3333. default:
  3334. break;
  3335. }
  3336. this.tip = block.parent || this.top;
  3337. };
  3338. // Walk through a block & children recursively, parsing string content
  3339. // into inline content where appropriate.
  3340. var processInlines = function(block) {
  3341. switch(block.t) {
  3342. case 'Paragraph':
  3343. case 'SetextHeader':
  3344. case 'ATXHeader':
  3345. block.inline_content =
  3346. this.inlineParser.parse(block.string_content.trim(), this.refmap);
  3347. block.string_content = "";
  3348. break;
  3349. default:
  3350. break;
  3351. }
  3352. if (block.children) {
  3353. for (var i = 0; i < block.children.length; i++) {
  3354. this.processInlines(block.children[i]);
  3355. }
  3356. }
  3357. };
  3358. // The main parsing function. Returns a parsed document AST.
  3359. var parse = function(input) {
  3360. this.doc = makeBlock('Document', 1, 1);
  3361. this.tip = this.doc;
  3362. this.refmap = {};
  3363. var lines = input.replace(/\n$/,'').split(/\r\n|\n|\r/);
  3364. var len = lines.length;
  3365. for (var i = 0; i < len; i++) {
  3366. this.incorporateLine(lines[i], i+1);
  3367. }
  3368. while (this.tip) {
  3369. this.finalize(this.tip, len - 1);
  3370. }
  3371. this.processInlines(this.doc);
  3372. return this.doc;
  3373. };
  3374. // The DocParser object.
  3375. function DocParser(){
  3376. return {
  3377. doc: makeBlock('Document', 1, 1),
  3378. tip: this.doc,
  3379. refmap: {},
  3380. inlineParser: new InlineParser(),
  3381. breakOutOfLists: breakOutOfLists,
  3382. addLine: addLine,
  3383. addChild: addChild,
  3384. incorporateLine: incorporateLine,
  3385. finalize: finalize,
  3386. processInlines: processInlines,
  3387. parse: parse
  3388. };
  3389. }
  3390. // HTML RENDERER
  3391. // Helper function to produce content in a pair of HTML tags.
  3392. var inTags = function(tag, attribs, contents, selfclosing) {
  3393. var result = '<' + tag;
  3394. if (attribs) {
  3395. var i = 0;
  3396. var attrib;
  3397. while ((attrib = attribs[i]) !== undefined) {
  3398. result = result.concat(' ', attrib[0], '="', attrib[1], '"');
  3399. i++;
  3400. }
  3401. }
  3402. if (contents) {
  3403. result = result.concat('>', contents, '</', tag, '>');
  3404. } else if (selfclosing) {
  3405. result = result + ' />';
  3406. } else {
  3407. result = result.concat('></', tag, '>');
  3408. }
  3409. return result;
  3410. };
  3411. // Render an inline element as HTML.
  3412. var renderInline = function(inline) {
  3413. var attrs;
  3414. switch (inline.t) {
  3415. case 'Str':
  3416. return this.escape(inline.c);
  3417. case 'Softbreak':
  3418. return this.softbreak;
  3419. case 'Hardbreak':
  3420. return inTags('br',[],"",true) + '\n';
  3421. case 'Emph':
  3422. return inTags('em', [], this.renderInlines(inline.c));
  3423. case 'Strong':
  3424. return inTags('strong', [], this.renderInlines(inline.c));
  3425. case 'Html':
  3426. return inline.c;
  3427. case 'Link':
  3428. attrs = [['href', this.escape(inline.destination, true)]];
  3429. if (inline.title) {
  3430. attrs.push(['title', this.escape(inline.title, true)]);
  3431. }
  3432. return inTags('a', attrs, this.renderInlines(inline.label));
  3433. case 'Image':
  3434. attrs = [['src', this.escape(inline.destination, true)],
  3435. ['alt', this.escape(this.renderInlines(inline.label))]];
  3436. if (inline.title) {
  3437. attrs.push(['title', this.escape(inline.title, true)]);
  3438. }
  3439. return inTags('img', attrs, "", true);
  3440. case 'Code':
  3441. return inTags('code', [], this.escape(inline.c));
  3442. default:
  3443. console.log("Unknown inline type " + inline.t);
  3444. return "";
  3445. }
  3446. };
  3447. // Render a list of inlines.
  3448. var renderInlines = function(inlines) {
  3449. var result = '';
  3450. for (var i=0; i < inlines.length; i++) {
  3451. result = result + this.renderInline(inlines[i]);
  3452. }
  3453. return result;
  3454. };
  3455. // Render a single block element.
  3456. var renderBlock = function(block, in_tight_list) {
  3457. var tag;
  3458. var attr;
  3459. var info_words;
  3460. switch (block.t) {
  3461. case 'Document':
  3462. var whole_doc = this.renderBlocks(block.children);
  3463. return (whole_doc === '' ? '' : whole_doc + '\n');
  3464. case 'Paragraph':
  3465. if (in_tight_list) {
  3466. return this.renderInlines(block.inline_content);
  3467. } else {
  3468. return inTags('p', [], this.renderInlines(block.inline_content));
  3469. }
  3470. break;
  3471. case 'BlockQuote':
  3472. var filling = this.renderBlocks(block.children);
  3473. return inTags('blockquote', [], filling === '' ? this.innersep :
  3474. this.innersep + filling + this.innersep);
  3475. case 'ListItem':
  3476. return inTags('li', [], this.renderBlocks(block.children, in_tight_list).trim());
  3477. case 'List':
  3478. tag = block.list_data.type == 'Bullet' ? 'ul' : 'ol';
  3479. attr = (!block.list_data.start || block.list_data.start == 1) ?
  3480. [] : [['start', block.list_data.start.toString()]];
  3481. return inTags(tag, attr, this.innersep +
  3482. this.renderBlocks(block.children, block.tight) +
  3483. this.innersep);
  3484. case 'ATXHeader':
  3485. case 'SetextHeader':
  3486. tag = 'h' + block.level;
  3487. return inTags(tag, [], this.renderInlines(block.inline_content));
  3488. case 'IndentedCode':
  3489. return inTags('pre', [],
  3490. inTags('code', [], this.escape(block.string_content)));
  3491. case 'FencedCode':
  3492. info_words = block.info.split(/ +/);
  3493. attr = info_words.length === 0 || info_words[0].length === 0 ?
  3494. [] : [['class','language-' +
  3495. this.escape(info_words[0],true)]];
  3496. return inTags('pre', [],
  3497. inTags('code', attr, this.escape(block.string_content)));
  3498. case 'HtmlBlock':
  3499. return block.string_content;
  3500. case 'ReferenceDef':
  3501. return "";
  3502. case 'HorizontalRule':
  3503. return inTags('hr',[],"",true);
  3504. default:
  3505. console.log("Unknown block type " + block.t);
  3506. return "";
  3507. }
  3508. };
  3509. // Render a list of block elements, separated by this.blocksep.
  3510. var renderBlocks = function(blocks, in_tight_list) {
  3511. var result = [];
  3512. for (var i=0; i < blocks.length; i++) {
  3513. if (blocks[i].t !== 'ReferenceDef') {
  3514. result.push(this.renderBlock(blocks[i], in_tight_list));
  3515. }
  3516. }
  3517. return result.join(this.blocksep);
  3518. };
  3519. // The HtmlRenderer object.
  3520. function HtmlRenderer(){
  3521. return {
  3522. // default options:
  3523. blocksep: '\n', // space between blocks
  3524. innersep: '\n', // space between block container tag and contents
  3525. softbreak: '\n', // by default, soft breaks are rendered as newlines in HTML
  3526. // set to "<br />" to make them hard breaks
  3527. // set to " " if you want to ignore line wrapping in source
  3528. escape: function(s, preserve_entities) {
  3529. if (preserve_entities) {
  3530. return s.replace(/[&](?![#](x[a-f0-9]{1,8}|[0-9]{1,8});|[a-z][a-z0-9]{1,31};)/gi,'&amp;')
  3531. .replace(/[<]/g,'&lt;')
  3532. .replace(/[>]/g,'&gt;')
  3533. .replace(/["]/g,'&quot;');
  3534. } else {
  3535. return s.replace(/[&]/g,'&amp;')
  3536. .replace(/[<]/g,'&lt;')
  3537. .replace(/[>]/g,'&gt;')
  3538. .replace(/["]/g,'&quot;');
  3539. }
  3540. },
  3541. renderInline: renderInline,
  3542. renderInlines: renderInlines,
  3543. renderBlock: renderBlock,
  3544. renderBlocks: renderBlocks,
  3545. render: renderBlock
  3546. };
  3547. }
  3548. exports.DocParser = DocParser;
  3549. exports.HtmlRenderer = HtmlRenderer;
  3550. })(typeof exports === 'undefined' ? this.stmd = {} : exports);