aboutsummaryrefslogtreecommitdiff
path: root/js/stmd.js
blob: bc6b2d10903753df126a02a7451e8fe93582996f (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 firstend;
  2438. var firstpos;
  2439. var state = 0;
  2440. var can_close = false;
  2441. var can_open = false;
  2442. var last_emphasis_closer = null;
  2443. while (this.last_emphasis_closer[c] >= this.pos) {
  2444. res = this.scanDelims(cc);
  2445. numclosedelims = res.numdelims;
  2446. if (res.can_close) {
  2447. if (last_emphasis_closer === null ||
  2448. last_emphasis_closer < this.pos) {
  2449. last_emphasis_closer = this.pos;
  2450. }
  2451. if (numclosedelims === 3 && delims_to_match === 3) {
  2452. delims_to_match -= 3;
  2453. this.pos += 3;
  2454. current = [{t: 'Strong', c: [{t: 'Emph', c: current}]}];
  2455. } else if (numclosedelims >= 2 && delims_to_match >= 2) {
  2456. delims_to_match -= 2;
  2457. this.pos += 2;
  2458. firstend = current.length;
  2459. firstpos = this.pos;
  2460. current = [{t: 'Strong', c: current}];
  2461. } else if (numclosedelims >= 1 && delims_to_match >= 1) {
  2462. delims_to_match -= 1;
  2463. this.pos += 1;
  2464. firstend = current.length;
  2465. firstpos = this.pos;
  2466. current = [{t: 'Emph', c: current}];
  2467. } else {
  2468. if (!(this.parseInline(current,true))) {
  2469. break;
  2470. }
  2471. }
  2472. if (delims_to_match === 0) {
  2473. Array.prototype.push.apply(inlines, current);
  2474. return true;
  2475. }
  2476. } else if (!(this.parseInline(current,true))) {
  2477. break;
  2478. }
  2479. }
  2480. // we didn't match emphasis: fallback
  2481. inlines.push(Str(this.subject.slice(startpos,
  2482. startpos + delims_to_match)));
  2483. if (delims_to_match < numdelims) {
  2484. Array.prototype.push.apply(inlines, current.slice(0,firstend));
  2485. this.pos = firstpos;
  2486. } else { // delims_to_match === numdelims
  2487. this.pos = startpos + delims_to_match;
  2488. }
  2489. if (last_emphasis_closer) {
  2490. this.last_emphasis_closer[c] = last_emphasis_closer;
  2491. }
  2492. return true;
  2493. };
  2494. // Attempt to parse link title (sans quotes), returning the string
  2495. // or null if no match.
  2496. var parseLinkTitle = function() {
  2497. var title = this.match(reLinkTitle);
  2498. if (title) {
  2499. // chop off quotes from title and unescape:
  2500. return unescapeEntBS(title.substr(1, title.length - 2));
  2501. } else {
  2502. return null;
  2503. }
  2504. };
  2505. // Attempt to parse link destination, returning the string or
  2506. // null if no match.
  2507. var parseLinkDestination = function() {
  2508. var res = this.match(reLinkDestinationBraces);
  2509. if (res) { // chop off surrounding <..>:
  2510. return encodeURI(unescape(unescapeEntBS(res.substr(1, res.length - 2))));
  2511. } else {
  2512. res = this.match(reLinkDestination);
  2513. if (res !== null) {
  2514. return encodeURI(unescape(unescapeEntBS(res)));
  2515. } else {
  2516. return null;
  2517. }
  2518. }
  2519. };
  2520. // Attempt to parse a link label, returning number of characters parsed.
  2521. var parseLinkLabel = function() {
  2522. if (this.peek() != C_OPEN_BRACKET) {
  2523. return 0;
  2524. }
  2525. var startpos = this.pos;
  2526. var nest_level = 0;
  2527. if (this.label_nest_level > 0) {
  2528. // If we've already checked to the end of this subject
  2529. // for a label, even with a different starting [, we
  2530. // know we won't find one here and we can just return.
  2531. // This avoids lots of backtracking.
  2532. // Note: nest level 1 would be: [foo [bar]
  2533. // nest level 2 would be: [foo [bar [baz]
  2534. this.label_nest_level--;
  2535. return 0;
  2536. }
  2537. this.pos++; // advance past [
  2538. var c;
  2539. while ((c = this.peek()) && c != -1 && (c != C_CLOSE_BRACKET || nest_level > 0)) {
  2540. switch (c) {
  2541. case C_BACKTICK:
  2542. this.parseBackticks([]);
  2543. break;
  2544. case C_LESSTHAN:
  2545. if (!(this.parseAutolink([]) || this.parseHtmlTag([]))) {
  2546. this.pos++;
  2547. }
  2548. break;
  2549. case C_OPEN_BRACKET: // nested []
  2550. nest_level++;
  2551. this.pos++;
  2552. break;
  2553. case C_CLOSE_BRACKET: // nested []
  2554. nest_level--;
  2555. this.pos++;
  2556. break;
  2557. case C_BACKSLASH:
  2558. this.parseBackslash([]);
  2559. break;
  2560. default:
  2561. this.parseString([]);
  2562. }
  2563. }
  2564. if (c === C_CLOSE_BRACKET) {
  2565. this.label_nest_level = 0;
  2566. this.pos++; // advance past ]
  2567. return this.pos - startpos;
  2568. } else {
  2569. if (c === -1) {
  2570. this.label_nest_level = nest_level;
  2571. }
  2572. this.pos = startpos;
  2573. return 0;
  2574. }
  2575. };
  2576. // Parse raw link label, including surrounding [], and return
  2577. // inline contents. (Note: this is not a method of InlineParser.)
  2578. var parseRawLabel = function(s) {
  2579. // note: parse without a refmap; we don't want links to resolve
  2580. // in nested brackets!
  2581. return new InlineParser().parse(s.substr(1, s.length - 2), {});
  2582. };
  2583. // Attempt to parse a link. If successful, return the link.
  2584. var parseLink = function(inlines) {
  2585. var startpos = this.pos;
  2586. var reflabel;
  2587. var n;
  2588. var dest;
  2589. var title;
  2590. n = this.parseLinkLabel();
  2591. if (n === 0) {
  2592. return false;
  2593. }
  2594. var afterlabel = this.pos;
  2595. var rawlabel = this.subject.substr(startpos, n);
  2596. // if we got this far, we've parsed a label.
  2597. // Try to parse an explicit link: [label](url "title")
  2598. if (this.peek() == C_OPEN_PAREN) {
  2599. this.pos++;
  2600. if (this.spnl() &&
  2601. ((dest = this.parseLinkDestination()) !== null) &&
  2602. this.spnl() &&
  2603. // make sure there's a space before the title:
  2604. (/^\s/.test(this.subject.charAt(this.pos - 1)) &&
  2605. (title = this.parseLinkTitle() || '') || true) &&
  2606. this.spnl() &&
  2607. this.match(/^\)/)) {
  2608. inlines.push({ t: 'Link',
  2609. destination: dest,
  2610. title: title,
  2611. label: parseRawLabel(rawlabel) });
  2612. return true;
  2613. } else {
  2614. this.pos = startpos;
  2615. return false;
  2616. }
  2617. }
  2618. // If we're here, it wasn't an explicit link. Try to parse a reference link.
  2619. // first, see if there's another label
  2620. var savepos = this.pos;
  2621. this.spnl();
  2622. var beforelabel = this.pos;
  2623. n = this.parseLinkLabel();
  2624. if (n == 2) {
  2625. // empty second label
  2626. reflabel = rawlabel;
  2627. } else if (n > 0) {
  2628. reflabel = this.subject.slice(beforelabel, beforelabel + n);
  2629. } else {
  2630. this.pos = savepos;
  2631. reflabel = rawlabel;
  2632. }
  2633. // lookup rawlabel in refmap
  2634. var link = this.refmap[normalizeReference(reflabel)];
  2635. if (link) {
  2636. inlines.push({t: 'Link',
  2637. destination: link.destination,
  2638. title: link.title,
  2639. label: parseRawLabel(rawlabel) });
  2640. return true;
  2641. } else {
  2642. this.pos = startpos;
  2643. return false;
  2644. }
  2645. // Nothing worked, rewind:
  2646. this.pos = startpos;
  2647. return false;
  2648. };
  2649. // Attempt to parse an entity, return Entity object if successful.
  2650. var parseEntity = function(inlines) {
  2651. var m;
  2652. if ((m = this.match(reEntityHere))) {
  2653. inlines.push({ t: 'Str', c: entityToChar(m) });
  2654. return true;
  2655. } else {
  2656. return false;
  2657. }
  2658. };
  2659. // Parse a run of ordinary characters, or a single character with
  2660. // a special meaning in markdown, as a plain string, adding to inlines.
  2661. var parseString = function(inlines) {
  2662. var m;
  2663. if ((m = this.match(reMain))) {
  2664. inlines.push({ t: 'Str', c: m });
  2665. return true;
  2666. } else {
  2667. return false;
  2668. }
  2669. };
  2670. // Parse a newline. If it was preceded by two spaces, return a hard
  2671. // line break; otherwise a soft line break.
  2672. var parseNewline = function(inlines) {
  2673. var m = this.match(/^ *\n/);
  2674. if (m) {
  2675. if (m.length > 2) {
  2676. inlines.push({ t: 'Hardbreak' });
  2677. } else if (m.length > 0) {
  2678. inlines.push({ t: 'Softbreak' });
  2679. }
  2680. return true;
  2681. }
  2682. return false;
  2683. };
  2684. // Attempt to parse an image. If the opening '!' is not followed
  2685. // by a link, return a literal '!'.
  2686. var parseImage = function(inlines) {
  2687. if (this.match(/^!/)) {
  2688. var link = this.parseLink(inlines);
  2689. if (link) {
  2690. inlines[inlines.length - 1].t = 'Image';
  2691. return true;
  2692. } else {
  2693. inlines.push({ t: 'Str', c: '!' });
  2694. return true;
  2695. }
  2696. } else {
  2697. return false;
  2698. }
  2699. };
  2700. // Attempt to parse a link reference, modifying refmap.
  2701. var parseReference = function(s, refmap) {
  2702. this.subject = s;
  2703. this.pos = 0;
  2704. this.label_nest_level = 0;
  2705. var rawlabel;
  2706. var dest;
  2707. var title;
  2708. var matchChars;
  2709. var startpos = this.pos;
  2710. var match;
  2711. // label:
  2712. matchChars = this.parseLinkLabel();
  2713. if (matchChars === 0) {
  2714. return 0;
  2715. } else {
  2716. rawlabel = this.subject.substr(0, matchChars);
  2717. }
  2718. // colon:
  2719. if (this.peek() === C_COLON) {
  2720. this.pos++;
  2721. } else {
  2722. this.pos = startpos;
  2723. return 0;
  2724. }
  2725. // link url
  2726. this.spnl();
  2727. dest = this.parseLinkDestination();
  2728. if (dest === null || dest.length === 0) {
  2729. this.pos = startpos;
  2730. return 0;
  2731. }
  2732. var beforetitle = this.pos;
  2733. this.spnl();
  2734. title = this.parseLinkTitle();
  2735. if (title === null) {
  2736. title = '';
  2737. // rewind before spaces
  2738. this.pos = beforetitle;
  2739. }
  2740. // make sure we're at line end:
  2741. if (this.match(/^ *(?:\n|$)/) === null) {
  2742. this.pos = startpos;
  2743. return 0;
  2744. }
  2745. var normlabel = normalizeReference(rawlabel);
  2746. if (!refmap[normlabel]) {
  2747. refmap[normlabel] = { destination: dest, title: title };
  2748. }
  2749. return this.pos - startpos;
  2750. };
  2751. // Parse the next inline element in subject, advancing subject position.
  2752. // If memoize is set, memoize the result.
  2753. // On success, add the result to the inlines list, and return true.
  2754. // On failure, return false.
  2755. var parseInline = function(inlines, memoize) {
  2756. var startpos = this.pos;
  2757. var origlen = inlines.length;
  2758. var memoized = memoize && this.memo[startpos];
  2759. if (memoized) {
  2760. this.pos = memoized.endpos;
  2761. Array.prototype.push.apply(inlines, memoized.inline);
  2762. return true;
  2763. }
  2764. var c = this.peek();
  2765. if (c === -1) {
  2766. return false;
  2767. }
  2768. var res;
  2769. switch(c) {
  2770. case C_NEWLINE:
  2771. case C_SPACE:
  2772. res = this.parseNewline(inlines);
  2773. break;
  2774. case C_BACKSLASH:
  2775. res = this.parseBackslash(inlines);
  2776. break;
  2777. case C_BACKTICK:
  2778. res = this.parseBackticks(inlines);
  2779. break;
  2780. case C_ASTERISK:
  2781. case C_UNDERSCORE:
  2782. res = this.parseEmphasis(c, inlines);
  2783. break;
  2784. case C_OPEN_BRACKET:
  2785. res = this.parseLink(inlines);
  2786. break;
  2787. case C_BANG:
  2788. res = this.parseImage(inlines);
  2789. break;
  2790. case C_LESSTHAN:
  2791. res = this.parseAutolink(inlines) || this.parseHtmlTag(inlines);
  2792. break;
  2793. case C_AMPERSAND:
  2794. res = this.parseEntity(inlines);
  2795. break;
  2796. default:
  2797. res = this.parseString(inlines);
  2798. break;
  2799. }
  2800. if (!res) {
  2801. this.pos += 1;
  2802. inlines.push({t: 'Str', c: String.fromCharCode(c)});
  2803. }
  2804. if (memoize) {
  2805. this.memo[startpos] = { inline: inlines.slice(origlen),
  2806. endpos: this.pos };
  2807. }
  2808. return true;
  2809. };
  2810. // Parse s as a list of inlines, using refmap to resolve references.
  2811. var parseInlines = function(s, refmap) {
  2812. this.subject = s;
  2813. this.pos = 0;
  2814. this.refmap = refmap || {};
  2815. this.memo = {};
  2816. this.last_emphasis_closer = { '*': s.length, '_': s.length };
  2817. var inlines = [];
  2818. while (this.parseInline(inlines, false)) {
  2819. }
  2820. return inlines;
  2821. };
  2822. // The InlineParser object.
  2823. function InlineParser(){
  2824. return {
  2825. subject: '',
  2826. label_nest_level: 0, // used by parseLinkLabel method
  2827. last_emphasis_closer: null, // used by parseEmphasis method
  2828. pos: 0,
  2829. refmap: {},
  2830. memo: {},
  2831. match: match,
  2832. peek: peek,
  2833. spnl: spnl,
  2834. parseBackticks: parseBackticks,
  2835. parseBackslash: parseBackslash,
  2836. parseAutolink: parseAutolink,
  2837. parseHtmlTag: parseHtmlTag,
  2838. scanDelims: scanDelims,
  2839. parseEmphasis: parseEmphasis,
  2840. parseLinkTitle: parseLinkTitle,
  2841. parseLinkDestination: parseLinkDestination,
  2842. parseLinkLabel: parseLinkLabel,
  2843. parseLink: parseLink,
  2844. parseEntity: parseEntity,
  2845. parseString: parseString,
  2846. parseNewline: parseNewline,
  2847. parseImage: parseImage,
  2848. parseReference: parseReference,
  2849. parseInline: parseInline,
  2850. parse: parseInlines
  2851. };
  2852. }
  2853. // DOC PARSER
  2854. // These are methods of a DocParser object, defined below.
  2855. var makeBlock = function(tag, start_line, start_column) {
  2856. return { t: tag,
  2857. open: true,
  2858. last_line_blank: false,
  2859. start_line: start_line,
  2860. start_column: start_column,
  2861. end_line: start_line,
  2862. children: [],
  2863. parent: null,
  2864. // string_content is formed by concatenating strings, in finalize:
  2865. string_content: "",
  2866. strings: [],
  2867. inline_content: []
  2868. };
  2869. };
  2870. // Returns true if parent block can contain child block.
  2871. var canContain = function(parent_type, child_type) {
  2872. return ( parent_type == 'Document' ||
  2873. parent_type == 'BlockQuote' ||
  2874. parent_type == 'ListItem' ||
  2875. (parent_type == 'List' && child_type == 'ListItem') );
  2876. };
  2877. // Returns true if block type can accept lines of text.
  2878. var acceptsLines = function(block_type) {
  2879. return ( block_type == 'Paragraph' ||
  2880. block_type == 'IndentedCode' ||
  2881. block_type == 'FencedCode' );
  2882. };
  2883. // Returns true if block ends with a blank line, descending if needed
  2884. // into lists and sublists.
  2885. var endsWithBlankLine = function(block) {
  2886. if (block.last_line_blank) {
  2887. return true;
  2888. }
  2889. if ((block.t == 'List' || block.t == 'ListItem') && block.children.length > 0) {
  2890. return endsWithBlankLine(block.children[block.children.length - 1]);
  2891. } else {
  2892. return false;
  2893. }
  2894. };
  2895. // Break out of all containing lists, resetting the tip of the
  2896. // document to the parent of the highest list, and finalizing
  2897. // all the lists. (This is used to implement the "two blank lines
  2898. // break of of all lists" feature.)
  2899. var breakOutOfLists = function(block, line_number) {
  2900. var b = block;
  2901. var last_list = null;
  2902. do {
  2903. if (b.t === 'List') {
  2904. last_list = b;
  2905. }
  2906. b = b.parent;
  2907. } while (b);
  2908. if (last_list) {
  2909. while (block != last_list) {
  2910. this.finalize(block, line_number);
  2911. block = block.parent;
  2912. }
  2913. this.finalize(last_list, line_number);
  2914. this.tip = last_list.parent;
  2915. }
  2916. };
  2917. // Add a line to the block at the tip. We assume the tip
  2918. // can accept lines -- that check should be done before calling this.
  2919. var addLine = function(ln, offset) {
  2920. var s = ln.slice(offset);
  2921. if (!(this.tip.open)) {
  2922. throw({ msg: "Attempted to add line (" + ln + ") to closed container." });
  2923. }
  2924. this.tip.strings.push(s);
  2925. };
  2926. // Add block of type tag as a child of the tip. If the tip can't
  2927. // accept children, close and finalize it and try its parent,
  2928. // and so on til we find a block that can accept children.
  2929. var addChild = function(tag, line_number, offset) {
  2930. while (!canContain(this.tip.t, tag)) {
  2931. this.finalize(this.tip, line_number);
  2932. }
  2933. var column_number = offset + 1; // offset 0 = column 1
  2934. var newBlock = makeBlock(tag, line_number, column_number);
  2935. this.tip.children.push(newBlock);
  2936. newBlock.parent = this.tip;
  2937. this.tip = newBlock;
  2938. return newBlock;
  2939. };
  2940. // Parse a list marker and return data on the marker (type,
  2941. // start, delimiter, bullet character, padding) or null.
  2942. var parseListMarker = function(ln, offset) {
  2943. var rest = ln.slice(offset);
  2944. var match;
  2945. var spaces_after_marker;
  2946. var data = {};
  2947. if (rest.match(reHrule)) {
  2948. return null;
  2949. }
  2950. if ((match = rest.match(/^[*+-]( +|$)/))) {
  2951. spaces_after_marker = match[1].length;
  2952. data.type = 'Bullet';
  2953. data.bullet_char = match[0][0];
  2954. } else if ((match = rest.match(/^(\d+)([.)])( +|$)/))) {
  2955. spaces_after_marker = match[3].length;
  2956. data.type = 'Ordered';
  2957. data.start = parseInt(match[1]);
  2958. data.delimiter = match[2];
  2959. } else {
  2960. return null;
  2961. }
  2962. var blank_item = match[0].length === rest.length;
  2963. if (spaces_after_marker >= 5 ||
  2964. spaces_after_marker < 1 ||
  2965. blank_item) {
  2966. data.padding = match[0].length - spaces_after_marker + 1;
  2967. } else {
  2968. data.padding = match[0].length;
  2969. }
  2970. return data;
  2971. };
  2972. // Returns true if the two list items are of the same type,
  2973. // with the same delimiter and bullet character. This is used
  2974. // in agglomerating list items into lists.
  2975. var listsMatch = function(list_data, item_data) {
  2976. return (list_data.type === item_data.type &&
  2977. list_data.delimiter === item_data.delimiter &&
  2978. list_data.bullet_char === item_data.bullet_char);
  2979. };
  2980. // Analyze a line of text and update the document appropriately.
  2981. // We parse markdown text by calling this on each line of input,
  2982. // then finalizing the document.
  2983. var incorporateLine = function(ln, line_number) {
  2984. var all_matched = true;
  2985. var last_child;
  2986. var first_nonspace;
  2987. var offset = 0;
  2988. var match;
  2989. var data;
  2990. var blank;
  2991. var indent;
  2992. var last_matched_container;
  2993. var i;
  2994. var CODE_INDENT = 4;
  2995. var container = this.doc;
  2996. var oldtip = this.tip;
  2997. // Convert tabs to spaces:
  2998. ln = detabLine(ln);
  2999. // For each containing block, try to parse the associated line start.
  3000. // Bail out on failure: container will point to the last matching block.
  3001. // Set all_matched to false if not all containers match.
  3002. while (container.children.length > 0) {
  3003. last_child = container.children[container.children.length - 1];
  3004. if (!last_child.open) {
  3005. break;
  3006. }
  3007. container = last_child;
  3008. match = matchAt(/[^ ]/, ln, offset);
  3009. if (match === null) {
  3010. first_nonspace = ln.length;
  3011. blank = true;
  3012. } else {
  3013. first_nonspace = match;
  3014. blank = false;
  3015. }
  3016. indent = first_nonspace - offset;
  3017. switch (container.t) {
  3018. case 'BlockQuote':
  3019. if (indent <= 3 && ln.charCodeAt(first_nonspace) === C_GREATERTHAN) {
  3020. offset = first_nonspace + 1;
  3021. if (ln.charCodeAt(offset) === C_SPACE) {
  3022. offset++;
  3023. }
  3024. } else {
  3025. all_matched = false;
  3026. }
  3027. break;
  3028. case 'ListItem':
  3029. if (indent >= container.list_data.marker_offset +
  3030. container.list_data.padding) {
  3031. offset += container.list_data.marker_offset +
  3032. container.list_data.padding;
  3033. } else if (blank) {
  3034. offset = first_nonspace;
  3035. } else {
  3036. all_matched = false;
  3037. }
  3038. break;
  3039. case 'IndentedCode':
  3040. if (indent >= CODE_INDENT) {
  3041. offset += CODE_INDENT;
  3042. } else if (blank) {
  3043. offset = first_nonspace;
  3044. } else {
  3045. all_matched = false;
  3046. }
  3047. break;
  3048. case 'ATXHeader':
  3049. case 'SetextHeader':
  3050. case 'HorizontalRule':
  3051. // a header can never container > 1 line, so fail to match:
  3052. all_matched = false;
  3053. break;
  3054. case 'FencedCode':
  3055. // skip optional spaces of fence offset
  3056. i = container.fence_offset;
  3057. while (i > 0 && ln.charCodeAt(offset) === C_SPACE) {
  3058. offset++;
  3059. i--;
  3060. }
  3061. break;
  3062. case 'HtmlBlock':
  3063. if (blank) {
  3064. all_matched = false;
  3065. }
  3066. break;
  3067. case 'Paragraph':
  3068. if (blank) {
  3069. container.last_line_blank = true;
  3070. all_matched = false;
  3071. }
  3072. break;
  3073. default:
  3074. }
  3075. if (!all_matched) {
  3076. container = container.parent; // back up to last matching block
  3077. break;
  3078. }
  3079. }
  3080. last_matched_container = container;
  3081. // This function is used to finalize and close any unmatched
  3082. // blocks. We aren't ready to do this now, because we might
  3083. // have a lazy paragraph continuation, in which case we don't
  3084. // want to close unmatched blocks. So we store this closure for
  3085. // use later, when we have more information.
  3086. var closeUnmatchedBlocks = function(mythis) {
  3087. // finalize any blocks not matched
  3088. while (!already_done && oldtip != last_matched_container) {
  3089. mythis.finalize(oldtip, line_number);
  3090. oldtip = oldtip.parent;
  3091. }
  3092. var already_done = true;
  3093. };
  3094. // Check to see if we've hit 2nd blank line; if so break out of list:
  3095. if (blank && container.last_line_blank) {
  3096. this.breakOutOfLists(container, line_number);
  3097. }
  3098. // Unless last matched container is a code block, try new container starts,
  3099. // adding children to the last matched container:
  3100. while (container.t != 'FencedCode' &&
  3101. container.t != 'IndentedCode' &&
  3102. container.t != 'HtmlBlock' &&
  3103. // this is a little performance optimization:
  3104. matchAt(/^[ #`~*+_=<>0-9-]/,ln,offset) !== null) {
  3105. match = matchAt(/[^ ]/, ln, offset);
  3106. if (match === null) {
  3107. first_nonspace = ln.length;
  3108. blank = true;
  3109. } else {
  3110. first_nonspace = match;
  3111. blank = false;
  3112. }
  3113. indent = first_nonspace - offset;
  3114. if (indent >= CODE_INDENT) {
  3115. // indented code
  3116. if (this.tip.t != 'Paragraph' && !blank) {
  3117. offset += CODE_INDENT;
  3118. closeUnmatchedBlocks(this);
  3119. container = this.addChild('IndentedCode', line_number, offset);
  3120. } else { // indent > 4 in a lazy paragraph continuation
  3121. break;
  3122. }
  3123. } else if (ln.charCodeAt(first_nonspace) === C_GREATERTHAN) {
  3124. // blockquote
  3125. offset = first_nonspace + 1;
  3126. // optional following space
  3127. if (ln.charCodeAt(offset) === C_SPACE) {
  3128. offset++;
  3129. }
  3130. closeUnmatchedBlocks(this);
  3131. container = this.addChild('BlockQuote', line_number, offset);
  3132. } else if ((match = ln.slice(first_nonspace).match(/^#{1,6}(?: +|$)/))) {
  3133. // ATX header
  3134. offset = first_nonspace + match[0].length;
  3135. closeUnmatchedBlocks(this);
  3136. container = this.addChild('ATXHeader', line_number, first_nonspace);
  3137. container.level = match[0].trim().length; // number of #s
  3138. // remove trailing ###s:
  3139. container.strings =
  3140. [ln.slice(offset).replace(/(?:(\\#) *#*| *#+) *$/,'$1')];
  3141. break;
  3142. } else if ((match = ln.slice(first_nonspace).match(/^`{3,}(?!.*`)|^~{3,}(?!.*~)/))) {
  3143. // fenced code block
  3144. var fence_length = match[0].length;
  3145. closeUnmatchedBlocks(this);
  3146. container = this.addChild('FencedCode', line_number, first_nonspace);
  3147. container.fence_length = fence_length;
  3148. container.fence_char = match[0][0];
  3149. container.fence_offset = first_nonspace - offset;
  3150. offset = first_nonspace + fence_length;
  3151. break;
  3152. } else if (matchAt(reHtmlBlockOpen, ln, first_nonspace) !== null) {
  3153. // html block
  3154. closeUnmatchedBlocks(this);
  3155. container = this.addChild('HtmlBlock', line_number, first_nonspace);
  3156. // note, we don't adjust offset because the tag is part of the text
  3157. break;
  3158. } else if (container.t == 'Paragraph' &&
  3159. container.strings.length === 1 &&
  3160. ((match = ln.slice(first_nonspace).match(/^(?:=+|-+) *$/)))) {
  3161. // setext header line
  3162. closeUnmatchedBlocks(this);
  3163. container.t = 'SetextHeader'; // convert Paragraph to SetextHeader
  3164. container.level = match[0][0] === '=' ? 1 : 2;
  3165. offset = ln.length;
  3166. } else if (matchAt(reHrule, ln, first_nonspace) !== null) {
  3167. // hrule
  3168. closeUnmatchedBlocks(this);
  3169. container = this.addChild('HorizontalRule', line_number, first_nonspace);
  3170. offset = ln.length - 1;
  3171. break;
  3172. } else if ((data = parseListMarker(ln, first_nonspace))) {
  3173. // list item
  3174. closeUnmatchedBlocks(this);
  3175. data.marker_offset = indent;
  3176. offset = first_nonspace + data.padding;
  3177. // add the list if needed
  3178. if (container.t !== 'List' ||
  3179. !(listsMatch(container.list_data, data))) {
  3180. container = this.addChild('List', line_number, first_nonspace);
  3181. container.list_data = data;
  3182. }
  3183. // add the list item
  3184. container = this.addChild('ListItem', line_number, first_nonspace);
  3185. container.list_data = data;
  3186. } else {
  3187. break;
  3188. }
  3189. if (acceptsLines(container.t)) {
  3190. // if it's a line container, it can't contain other containers
  3191. break;
  3192. }
  3193. }
  3194. // What remains at the offset is a text line. Add the text to the
  3195. // appropriate container.
  3196. match = matchAt(/[^ ]/, ln, offset);
  3197. if (match === null) {
  3198. first_nonspace = ln.length;
  3199. blank = true;
  3200. } else {
  3201. first_nonspace = match;
  3202. blank = false;
  3203. }
  3204. indent = first_nonspace - offset;
  3205. // First check for a lazy paragraph continuation:
  3206. if (this.tip !== last_matched_container &&
  3207. !blank &&
  3208. this.tip.t == 'Paragraph' &&
  3209. this.tip.strings.length > 0) {
  3210. // lazy paragraph continuation
  3211. this.last_line_blank = false;
  3212. this.addLine(ln, offset);
  3213. } else { // not a lazy continuation
  3214. // finalize any blocks not matched
  3215. closeUnmatchedBlocks(this);
  3216. // Block quote lines are never blank as they start with >
  3217. // and we don't count blanks in fenced code for purposes of tight/loose
  3218. // lists or breaking out of lists. We also don't set last_line_blank
  3219. // on an empty list item.
  3220. container.last_line_blank = blank &&
  3221. !(container.t == 'BlockQuote' ||
  3222. container.t == 'FencedCode' ||
  3223. (container.t == 'ListItem' &&
  3224. container.children.length === 0 &&
  3225. container.start_line == line_number));
  3226. var cont = container;
  3227. while (cont.parent) {
  3228. cont.parent.last_line_blank = false;
  3229. cont = cont.parent;
  3230. }
  3231. switch (container.t) {
  3232. case 'IndentedCode':
  3233. case 'HtmlBlock':
  3234. this.addLine(ln, offset);
  3235. break;
  3236. case 'FencedCode':
  3237. // check for closing code fence:
  3238. match = (indent <= 3 &&
  3239. ln.charAt(first_nonspace) == container.fence_char &&
  3240. ln.slice(first_nonspace).match(/^(?:`{3,}|~{3,})(?= *$)/));
  3241. if (match && match[0].length >= container.fence_length) {
  3242. // don't add closing fence to container; instead, close it:
  3243. this.finalize(container, line_number);
  3244. } else {
  3245. this.addLine(ln, offset);
  3246. }
  3247. break;
  3248. case 'ATXHeader':
  3249. case 'SetextHeader':
  3250. case 'HorizontalRule':
  3251. // nothing to do; we already added the contents.
  3252. break;
  3253. default:
  3254. if (acceptsLines(container.t)) {
  3255. this.addLine(ln, first_nonspace);
  3256. } else if (blank) {
  3257. // do nothing
  3258. } else if (container.t != 'HorizontalRule' &&
  3259. container.t != 'SetextHeader') {
  3260. // create paragraph container for line
  3261. container = this.addChild('Paragraph', line_number, first_nonspace);
  3262. this.addLine(ln, first_nonspace);
  3263. } else {
  3264. console.log("Line " + line_number.toString() +
  3265. " with container type " + container.t +
  3266. " did not match any condition.");
  3267. }
  3268. }
  3269. }
  3270. };
  3271. // Finalize a block. Close it and do any necessary postprocessing,
  3272. // e.g. creating string_content from strings, setting the 'tight'
  3273. // or 'loose' status of a list, and parsing the beginnings
  3274. // of paragraphs for reference definitions. Reset the tip to the
  3275. // parent of the closed block.
  3276. var finalize = function(block, line_number) {
  3277. var pos;
  3278. // don't do anything if the block is already closed
  3279. if (!block.open) {
  3280. return 0;
  3281. }
  3282. block.open = false;
  3283. if (line_number > block.start_line) {
  3284. block.end_line = line_number - 1;
  3285. } else {
  3286. block.end_line = line_number;
  3287. }
  3288. switch (block.t) {
  3289. case 'Paragraph':
  3290. block.string_content = block.strings.join('\n').replace(/^ */m,'');
  3291. // try parsing the beginning as link reference definitions:
  3292. while (block.string_content.charCodeAt(0) === C_OPEN_BRACKET &&
  3293. (pos = this.inlineParser.parseReference(block.string_content,
  3294. this.refmap))) {
  3295. block.string_content = block.string_content.slice(pos);
  3296. if (isBlank(block.string_content)) {
  3297. block.t = 'ReferenceDef';
  3298. break;
  3299. }
  3300. }
  3301. break;
  3302. case 'ATXHeader':
  3303. case 'SetextHeader':
  3304. case 'HtmlBlock':
  3305. block.string_content = block.strings.join('\n');
  3306. break;
  3307. case 'IndentedCode':
  3308. block.string_content = block.strings.join('\n').replace(/(\n *)*$/,'\n');
  3309. break;
  3310. case 'FencedCode':
  3311. // first line becomes info string
  3312. block.info = unescapeEntBS(block.strings[0].trim());
  3313. if (block.strings.length == 1) {
  3314. block.string_content = '';
  3315. } else {
  3316. block.string_content = block.strings.slice(1).join('\n') + '\n';
  3317. }
  3318. break;
  3319. case 'List':
  3320. block.tight = true; // tight by default
  3321. var numitems = block.children.length;
  3322. var i = 0;
  3323. while (i < numitems) {
  3324. var item = block.children[i];
  3325. // check for non-final list item ending with blank line:
  3326. var last_item = i == numitems - 1;
  3327. if (endsWithBlankLine(item) && !last_item) {
  3328. block.tight = false;
  3329. break;
  3330. }
  3331. // recurse into children of list item, to see if there are
  3332. // spaces between any of them:
  3333. var numsubitems = item.children.length;
  3334. var j = 0;
  3335. while (j < numsubitems) {
  3336. var subitem = item.children[j];
  3337. var last_subitem = j == numsubitems - 1;
  3338. if (endsWithBlankLine(subitem) && !(last_item && last_subitem)) {
  3339. block.tight = false;
  3340. break;
  3341. }
  3342. j++;
  3343. }
  3344. i++;
  3345. }
  3346. break;
  3347. default:
  3348. break;
  3349. }
  3350. this.tip = block.parent || this.top;
  3351. };
  3352. // Walk through a block & children recursively, parsing string content
  3353. // into inline content where appropriate.
  3354. var processInlines = function(block) {
  3355. switch(block.t) {
  3356. case 'Paragraph':
  3357. case 'SetextHeader':
  3358. case 'ATXHeader':
  3359. block.inline_content =
  3360. this.inlineParser.parse(block.string_content.trim(), this.refmap);
  3361. block.string_content = "";
  3362. break;
  3363. default:
  3364. break;
  3365. }
  3366. if (block.children) {
  3367. for (var i = 0; i < block.children.length; i++) {
  3368. this.processInlines(block.children[i]);
  3369. }
  3370. }
  3371. };
  3372. // The main parsing function. Returns a parsed document AST.
  3373. var parse = function(input) {
  3374. this.doc = makeBlock('Document', 1, 1);
  3375. this.tip = this.doc;
  3376. this.refmap = {};
  3377. var lines = input.replace(/\n$/,'').split(/\r\n|\n|\r/);
  3378. var len = lines.length;
  3379. for (var i = 0; i < len; i++) {
  3380. this.incorporateLine(lines[i], i+1);
  3381. }
  3382. while (this.tip) {
  3383. this.finalize(this.tip, len - 1);
  3384. }
  3385. this.processInlines(this.doc);
  3386. return this.doc;
  3387. };
  3388. // The DocParser object.
  3389. function DocParser(){
  3390. return {
  3391. doc: makeBlock('Document', 1, 1),
  3392. tip: this.doc,
  3393. refmap: {},
  3394. inlineParser: new InlineParser(),
  3395. breakOutOfLists: breakOutOfLists,
  3396. addLine: addLine,
  3397. addChild: addChild,
  3398. incorporateLine: incorporateLine,
  3399. finalize: finalize,
  3400. processInlines: processInlines,
  3401. parse: parse
  3402. };
  3403. }
  3404. // HTML RENDERER
  3405. // Helper function to produce content in a pair of HTML tags.
  3406. var inTags = function(tag, attribs, contents, selfclosing) {
  3407. var result = '<' + tag;
  3408. if (attribs) {
  3409. var i = 0;
  3410. var attrib;
  3411. while ((attrib = attribs[i]) !== undefined) {
  3412. result = result.concat(' ', attrib[0], '="', attrib[1], '"');
  3413. i++;
  3414. }
  3415. }
  3416. if (contents) {
  3417. result = result.concat('>', contents, '</', tag, '>');
  3418. } else if (selfclosing) {
  3419. result = result + ' />';
  3420. } else {
  3421. result = result.concat('></', tag, '>');
  3422. }
  3423. return result;
  3424. };
  3425. // Render an inline element as HTML.
  3426. var renderInline = function(inline) {
  3427. var attrs;
  3428. switch (inline.t) {
  3429. case 'Str':
  3430. return this.escape(inline.c);
  3431. case 'Softbreak':
  3432. return this.softbreak;
  3433. case 'Hardbreak':
  3434. return inTags('br',[],"",true) + '\n';
  3435. case 'Emph':
  3436. return inTags('em', [], this.renderInlines(inline.c));
  3437. case 'Strong':
  3438. return inTags('strong', [], this.renderInlines(inline.c));
  3439. case 'Html':
  3440. return inline.c;
  3441. case 'Link':
  3442. attrs = [['href', this.escape(inline.destination, true)]];
  3443. if (inline.title) {
  3444. attrs.push(['title', this.escape(inline.title, true)]);
  3445. }
  3446. return inTags('a', attrs, this.renderInlines(inline.label));
  3447. case 'Image':
  3448. attrs = [['src', this.escape(inline.destination, true)],
  3449. ['alt', this.escape(this.renderInlines(inline.label))]];
  3450. if (inline.title) {
  3451. attrs.push(['title', this.escape(inline.title, true)]);
  3452. }
  3453. return inTags('img', attrs, "", true);
  3454. case 'Code':
  3455. return inTags('code', [], this.escape(inline.c));
  3456. default:
  3457. console.log("Unknown inline type " + inline.t);
  3458. return "";
  3459. }
  3460. };
  3461. // Render a list of inlines.
  3462. var renderInlines = function(inlines) {
  3463. var result = '';
  3464. for (var i=0; i < inlines.length; i++) {
  3465. result = result + this.renderInline(inlines[i]);
  3466. }
  3467. return result;
  3468. };
  3469. // Render a single block element.
  3470. var renderBlock = function(block, in_tight_list) {
  3471. var tag;
  3472. var attr;
  3473. var info_words;
  3474. switch (block.t) {
  3475. case 'Document':
  3476. var whole_doc = this.renderBlocks(block.children);
  3477. return (whole_doc === '' ? '' : whole_doc + '\n');
  3478. case 'Paragraph':
  3479. if (in_tight_list) {
  3480. return this.renderInlines(block.inline_content);
  3481. } else {
  3482. return inTags('p', [], this.renderInlines(block.inline_content));
  3483. }
  3484. break;
  3485. case 'BlockQuote':
  3486. var filling = this.renderBlocks(block.children);
  3487. return inTags('blockquote', [], filling === '' ? this.innersep :
  3488. this.innersep + filling + this.innersep);
  3489. case 'ListItem':
  3490. return inTags('li', [], this.renderBlocks(block.children, in_tight_list).trim());
  3491. case 'List':
  3492. tag = block.list_data.type == 'Bullet' ? 'ul' : 'ol';
  3493. attr = (!block.list_data.start || block.list_data.start == 1) ?
  3494. [] : [['start', block.list_data.start.toString()]];
  3495. return inTags(tag, attr, this.innersep +
  3496. this.renderBlocks(block.children, block.tight) +
  3497. this.innersep);
  3498. case 'ATXHeader':
  3499. case 'SetextHeader':
  3500. tag = 'h' + block.level;
  3501. return inTags(tag, [], this.renderInlines(block.inline_content));
  3502. case 'IndentedCode':
  3503. return inTags('pre', [],
  3504. inTags('code', [], this.escape(block.string_content)));
  3505. case 'FencedCode':
  3506. info_words = block.info.split(/ +/);
  3507. attr = info_words.length === 0 || info_words[0].length === 0 ?
  3508. [] : [['class','language-' +
  3509. this.escape(info_words[0],true)]];
  3510. return inTags('pre', [],
  3511. inTags('code', attr, this.escape(block.string_content)));
  3512. case 'HtmlBlock':
  3513. return block.string_content;
  3514. case 'ReferenceDef':
  3515. return "";
  3516. case 'HorizontalRule':
  3517. return inTags('hr',[],"",true);
  3518. default:
  3519. console.log("Unknown block type " + block.t);
  3520. return "";
  3521. }
  3522. };
  3523. // Render a list of block elements, separated by this.blocksep.
  3524. var renderBlocks = function(blocks, in_tight_list) {
  3525. var result = [];
  3526. for (var i=0; i < blocks.length; i++) {
  3527. if (blocks[i].t !== 'ReferenceDef') {
  3528. result.push(this.renderBlock(blocks[i], in_tight_list));
  3529. }
  3530. }
  3531. return result.join(this.blocksep);
  3532. };
  3533. // The HtmlRenderer object.
  3534. function HtmlRenderer(){
  3535. return {
  3536. // default options:
  3537. blocksep: '\n', // space between blocks
  3538. innersep: '\n', // space between block container tag and contents
  3539. softbreak: '\n', // by default, soft breaks are rendered as newlines in HTML
  3540. // set to "<br />" to make them hard breaks
  3541. // set to " " if you want to ignore line wrapping in source
  3542. escape: function(s, preserve_entities) {
  3543. if (preserve_entities) {
  3544. return s.replace(/[&](?![#](x[a-f0-9]{1,8}|[0-9]{1,8});|[a-z][a-z0-9]{1,31};)/gi,'&amp;')
  3545. .replace(/[<]/g,'&lt;')
  3546. .replace(/[>]/g,'&gt;')
  3547. .replace(/["]/g,'&quot;');
  3548. } else {
  3549. return s.replace(/[&]/g,'&amp;')
  3550. .replace(/[<]/g,'&lt;')
  3551. .replace(/[>]/g,'&gt;')
  3552. .replace(/["]/g,'&quot;');
  3553. }
  3554. },
  3555. renderInline: renderInline,
  3556. renderInlines: renderInlines,
  3557. renderBlock: renderBlock,
  3558. renderBlocks: renderBlocks,
  3559. render: renderBlock
  3560. };
  3561. }
  3562. exports.DocParser = DocParser;
  3563. exports.HtmlRenderer = HtmlRenderer;
  3564. })(typeof exports === 'undefined' ? this.stmd = {} : exports);