12882 lines
319 KiB
JavaScript
12882 lines
319 KiB
JavaScript
/*
|
||
THIS IS A GENERATED/BUNDLED FILE BY ROLLUP
|
||
if you want to view the source visit the plugins github repository
|
||
*/
|
||
|
||
'use strict';
|
||
|
||
var obsidian = require('obsidian');
|
||
|
||
/*! *****************************************************************************
|
||
Copyright (c) Microsoft Corporation.
|
||
|
||
Permission to use, copy, modify, and/or distribute this software for any
|
||
purpose with or without fee is hereby granted.
|
||
|
||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||
PERFORMANCE OF THIS SOFTWARE.
|
||
***************************************************************************** */
|
||
|
||
function __awaiter(thisArg, _arguments, P, generator) {
|
||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
||
return new (P || (P = Promise))(function (resolve, reject) {
|
||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||
});
|
||
}
|
||
|
||
var utils$1 = {};
|
||
|
||
var Aacute = "Á";
|
||
var aacute = "á";
|
||
var Abreve = "Ă";
|
||
var abreve = "ă";
|
||
var ac = "∾";
|
||
var acd = "∿";
|
||
var acE = "∾̳";
|
||
var Acirc = "Â";
|
||
var acirc = "â";
|
||
var acute = "´";
|
||
var Acy = "А";
|
||
var acy = "а";
|
||
var AElig = "Æ";
|
||
var aelig = "æ";
|
||
var af = "";
|
||
var Afr = "𝔄";
|
||
var afr = "𝔞";
|
||
var Agrave = "À";
|
||
var agrave = "à";
|
||
var alefsym = "ℵ";
|
||
var aleph = "ℵ";
|
||
var Alpha = "Α";
|
||
var alpha = "α";
|
||
var Amacr = "Ā";
|
||
var amacr = "ā";
|
||
var amalg = "⨿";
|
||
var amp = "&";
|
||
var AMP = "&";
|
||
var andand = "⩕";
|
||
var And = "⩓";
|
||
var and = "∧";
|
||
var andd = "⩜";
|
||
var andslope = "⩘";
|
||
var andv = "⩚";
|
||
var ang = "∠";
|
||
var ange = "⦤";
|
||
var angle = "∠";
|
||
var angmsdaa = "⦨";
|
||
var angmsdab = "⦩";
|
||
var angmsdac = "⦪";
|
||
var angmsdad = "⦫";
|
||
var angmsdae = "⦬";
|
||
var angmsdaf = "⦭";
|
||
var angmsdag = "⦮";
|
||
var angmsdah = "⦯";
|
||
var angmsd = "∡";
|
||
var angrt = "∟";
|
||
var angrtvb = "⊾";
|
||
var angrtvbd = "⦝";
|
||
var angsph = "∢";
|
||
var angst = "Å";
|
||
var angzarr = "⍼";
|
||
var Aogon = "Ą";
|
||
var aogon = "ą";
|
||
var Aopf = "𝔸";
|
||
var aopf = "𝕒";
|
||
var apacir = "⩯";
|
||
var ap = "≈";
|
||
var apE = "⩰";
|
||
var ape = "≊";
|
||
var apid = "≋";
|
||
var apos = "'";
|
||
var ApplyFunction = "";
|
||
var approx = "≈";
|
||
var approxeq = "≊";
|
||
var Aring = "Å";
|
||
var aring = "å";
|
||
var Ascr = "𝒜";
|
||
var ascr = "𝒶";
|
||
var Assign = "≔";
|
||
var ast = "*";
|
||
var asymp = "≈";
|
||
var asympeq = "≍";
|
||
var Atilde = "Ã";
|
||
var atilde = "ã";
|
||
var Auml = "Ä";
|
||
var auml = "ä";
|
||
var awconint = "∳";
|
||
var awint = "⨑";
|
||
var backcong = "≌";
|
||
var backepsilon = "϶";
|
||
var backprime = "‵";
|
||
var backsim = "∽";
|
||
var backsimeq = "⋍";
|
||
var Backslash = "∖";
|
||
var Barv = "⫧";
|
||
var barvee = "⊽";
|
||
var barwed = "⌅";
|
||
var Barwed = "⌆";
|
||
var barwedge = "⌅";
|
||
var bbrk = "⎵";
|
||
var bbrktbrk = "⎶";
|
||
var bcong = "≌";
|
||
var Bcy = "Б";
|
||
var bcy = "б";
|
||
var bdquo = "„";
|
||
var becaus = "∵";
|
||
var because = "∵";
|
||
var Because = "∵";
|
||
var bemptyv = "⦰";
|
||
var bepsi = "϶";
|
||
var bernou = "ℬ";
|
||
var Bernoullis = "ℬ";
|
||
var Beta = "Β";
|
||
var beta = "β";
|
||
var beth = "ℶ";
|
||
var between = "≬";
|
||
var Bfr = "𝔅";
|
||
var bfr = "𝔟";
|
||
var bigcap = "⋂";
|
||
var bigcirc = "◯";
|
||
var bigcup = "⋃";
|
||
var bigodot = "⨀";
|
||
var bigoplus = "⨁";
|
||
var bigotimes = "⨂";
|
||
var bigsqcup = "⨆";
|
||
var bigstar = "★";
|
||
var bigtriangledown = "▽";
|
||
var bigtriangleup = "△";
|
||
var biguplus = "⨄";
|
||
var bigvee = "⋁";
|
||
var bigwedge = "⋀";
|
||
var bkarow = "⤍";
|
||
var blacklozenge = "⧫";
|
||
var blacksquare = "▪";
|
||
var blacktriangle = "▴";
|
||
var blacktriangledown = "▾";
|
||
var blacktriangleleft = "◂";
|
||
var blacktriangleright = "▸";
|
||
var blank = "␣";
|
||
var blk12 = "▒";
|
||
var blk14 = "░";
|
||
var blk34 = "▓";
|
||
var block$1 = "█";
|
||
var bne = "=⃥";
|
||
var bnequiv = "≡⃥";
|
||
var bNot = "⫭";
|
||
var bnot = "⌐";
|
||
var Bopf = "𝔹";
|
||
var bopf = "𝕓";
|
||
var bot = "⊥";
|
||
var bottom = "⊥";
|
||
var bowtie = "⋈";
|
||
var boxbox = "⧉";
|
||
var boxdl = "┐";
|
||
var boxdL = "╕";
|
||
var boxDl = "╖";
|
||
var boxDL = "╗";
|
||
var boxdr = "┌";
|
||
var boxdR = "╒";
|
||
var boxDr = "╓";
|
||
var boxDR = "╔";
|
||
var boxh = "─";
|
||
var boxH = "═";
|
||
var boxhd = "┬";
|
||
var boxHd = "╤";
|
||
var boxhD = "╥";
|
||
var boxHD = "╦";
|
||
var boxhu = "┴";
|
||
var boxHu = "╧";
|
||
var boxhU = "╨";
|
||
var boxHU = "╩";
|
||
var boxminus = "⊟";
|
||
var boxplus = "⊞";
|
||
var boxtimes = "⊠";
|
||
var boxul = "┘";
|
||
var boxuL = "╛";
|
||
var boxUl = "╜";
|
||
var boxUL = "╝";
|
||
var boxur = "└";
|
||
var boxuR = "╘";
|
||
var boxUr = "╙";
|
||
var boxUR = "╚";
|
||
var boxv = "│";
|
||
var boxV = "║";
|
||
var boxvh = "┼";
|
||
var boxvH = "╪";
|
||
var boxVh = "╫";
|
||
var boxVH = "╬";
|
||
var boxvl = "┤";
|
||
var boxvL = "╡";
|
||
var boxVl = "╢";
|
||
var boxVL = "╣";
|
||
var boxvr = "├";
|
||
var boxvR = "╞";
|
||
var boxVr = "╟";
|
||
var boxVR = "╠";
|
||
var bprime = "‵";
|
||
var breve = "˘";
|
||
var Breve = "˘";
|
||
var brvbar = "¦";
|
||
var bscr = "𝒷";
|
||
var Bscr = "ℬ";
|
||
var bsemi = "⁏";
|
||
var bsim = "∽";
|
||
var bsime = "⋍";
|
||
var bsolb = "⧅";
|
||
var bsol = "\\";
|
||
var bsolhsub = "⟈";
|
||
var bull = "•";
|
||
var bullet = "•";
|
||
var bump = "≎";
|
||
var bumpE = "⪮";
|
||
var bumpe = "≏";
|
||
var Bumpeq = "≎";
|
||
var bumpeq = "≏";
|
||
var Cacute = "Ć";
|
||
var cacute = "ć";
|
||
var capand = "⩄";
|
||
var capbrcup = "⩉";
|
||
var capcap = "⩋";
|
||
var cap = "∩";
|
||
var Cap = "⋒";
|
||
var capcup = "⩇";
|
||
var capdot = "⩀";
|
||
var CapitalDifferentialD = "ⅅ";
|
||
var caps = "∩︀";
|
||
var caret = "⁁";
|
||
var caron = "ˇ";
|
||
var Cayleys = "ℭ";
|
||
var ccaps = "⩍";
|
||
var Ccaron = "Č";
|
||
var ccaron = "č";
|
||
var Ccedil = "Ç";
|
||
var ccedil = "ç";
|
||
var Ccirc = "Ĉ";
|
||
var ccirc = "ĉ";
|
||
var Cconint = "∰";
|
||
var ccups = "⩌";
|
||
var ccupssm = "⩐";
|
||
var Cdot = "Ċ";
|
||
var cdot = "ċ";
|
||
var cedil = "¸";
|
||
var Cedilla = "¸";
|
||
var cemptyv = "⦲";
|
||
var cent = "¢";
|
||
var centerdot = "·";
|
||
var CenterDot = "·";
|
||
var cfr = "𝔠";
|
||
var Cfr = "ℭ";
|
||
var CHcy = "Ч";
|
||
var chcy = "ч";
|
||
var check = "✓";
|
||
var checkmark = "✓";
|
||
var Chi = "Χ";
|
||
var chi = "χ";
|
||
var circ = "ˆ";
|
||
var circeq = "≗";
|
||
var circlearrowleft = "↺";
|
||
var circlearrowright = "↻";
|
||
var circledast = "⊛";
|
||
var circledcirc = "⊚";
|
||
var circleddash = "⊝";
|
||
var CircleDot = "⊙";
|
||
var circledR = "®";
|
||
var circledS = "Ⓢ";
|
||
var CircleMinus = "⊖";
|
||
var CirclePlus = "⊕";
|
||
var CircleTimes = "⊗";
|
||
var cir = "○";
|
||
var cirE = "⧃";
|
||
var cire = "≗";
|
||
var cirfnint = "⨐";
|
||
var cirmid = "⫯";
|
||
var cirscir = "⧂";
|
||
var ClockwiseContourIntegral = "∲";
|
||
var CloseCurlyDoubleQuote = "”";
|
||
var CloseCurlyQuote = "’";
|
||
var clubs = "♣";
|
||
var clubsuit = "♣";
|
||
var colon = ":";
|
||
var Colon = "∷";
|
||
var Colone = "⩴";
|
||
var colone = "≔";
|
||
var coloneq = "≔";
|
||
var comma = ",";
|
||
var commat = "@";
|
||
var comp = "∁";
|
||
var compfn = "∘";
|
||
var complement = "∁";
|
||
var complexes = "ℂ";
|
||
var cong = "≅";
|
||
var congdot = "⩭";
|
||
var Congruent = "≡";
|
||
var conint = "∮";
|
||
var Conint = "∯";
|
||
var ContourIntegral = "∮";
|
||
var copf = "𝕔";
|
||
var Copf = "ℂ";
|
||
var coprod = "∐";
|
||
var Coproduct = "∐";
|
||
var copy = "©";
|
||
var COPY = "©";
|
||
var copysr = "℗";
|
||
var CounterClockwiseContourIntegral = "∳";
|
||
var crarr = "↵";
|
||
var cross = "✗";
|
||
var Cross = "⨯";
|
||
var Cscr = "𝒞";
|
||
var cscr = "𝒸";
|
||
var csub = "⫏";
|
||
var csube = "⫑";
|
||
var csup = "⫐";
|
||
var csupe = "⫒";
|
||
var ctdot = "⋯";
|
||
var cudarrl = "⤸";
|
||
var cudarrr = "⤵";
|
||
var cuepr = "⋞";
|
||
var cuesc = "⋟";
|
||
var cularr = "↶";
|
||
var cularrp = "⤽";
|
||
var cupbrcap = "⩈";
|
||
var cupcap = "⩆";
|
||
var CupCap = "≍";
|
||
var cup = "∪";
|
||
var Cup = "⋓";
|
||
var cupcup = "⩊";
|
||
var cupdot = "⊍";
|
||
var cupor = "⩅";
|
||
var cups = "∪︀";
|
||
var curarr = "↷";
|
||
var curarrm = "⤼";
|
||
var curlyeqprec = "⋞";
|
||
var curlyeqsucc = "⋟";
|
||
var curlyvee = "⋎";
|
||
var curlywedge = "⋏";
|
||
var curren = "¤";
|
||
var curvearrowleft = "↶";
|
||
var curvearrowright = "↷";
|
||
var cuvee = "⋎";
|
||
var cuwed = "⋏";
|
||
var cwconint = "∲";
|
||
var cwint = "∱";
|
||
var cylcty = "⌭";
|
||
var dagger = "†";
|
||
var Dagger = "‡";
|
||
var daleth = "ℸ";
|
||
var darr = "↓";
|
||
var Darr = "↡";
|
||
var dArr = "⇓";
|
||
var dash = "‐";
|
||
var Dashv = "⫤";
|
||
var dashv = "⊣";
|
||
var dbkarow = "⤏";
|
||
var dblac = "˝";
|
||
var Dcaron = "Ď";
|
||
var dcaron = "ď";
|
||
var Dcy = "Д";
|
||
var dcy = "д";
|
||
var ddagger = "‡";
|
||
var ddarr = "⇊";
|
||
var DD = "ⅅ";
|
||
var dd = "ⅆ";
|
||
var DDotrahd = "⤑";
|
||
var ddotseq = "⩷";
|
||
var deg = "°";
|
||
var Del = "∇";
|
||
var Delta = "Δ";
|
||
var delta = "δ";
|
||
var demptyv = "⦱";
|
||
var dfisht = "⥿";
|
||
var Dfr = "𝔇";
|
||
var dfr = "𝔡";
|
||
var dHar = "⥥";
|
||
var dharl = "⇃";
|
||
var dharr = "⇂";
|
||
var DiacriticalAcute = "´";
|
||
var DiacriticalDot = "˙";
|
||
var DiacriticalDoubleAcute = "˝";
|
||
var DiacriticalGrave = "`";
|
||
var DiacriticalTilde = "˜";
|
||
var diam = "⋄";
|
||
var diamond = "⋄";
|
||
var Diamond = "⋄";
|
||
var diamondsuit = "♦";
|
||
var diams = "♦";
|
||
var die = "¨";
|
||
var DifferentialD = "ⅆ";
|
||
var digamma = "ϝ";
|
||
var disin = "⋲";
|
||
var div = "÷";
|
||
var divide = "÷";
|
||
var divideontimes = "⋇";
|
||
var divonx = "⋇";
|
||
var DJcy = "Ђ";
|
||
var djcy = "ђ";
|
||
var dlcorn = "⌞";
|
||
var dlcrop = "⌍";
|
||
var dollar = "$";
|
||
var Dopf = "𝔻";
|
||
var dopf = "𝕕";
|
||
var Dot = "¨";
|
||
var dot = "˙";
|
||
var DotDot = "⃜";
|
||
var doteq = "≐";
|
||
var doteqdot = "≑";
|
||
var DotEqual = "≐";
|
||
var dotminus = "∸";
|
||
var dotplus = "∔";
|
||
var dotsquare = "⊡";
|
||
var doublebarwedge = "⌆";
|
||
var DoubleContourIntegral = "∯";
|
||
var DoubleDot = "¨";
|
||
var DoubleDownArrow = "⇓";
|
||
var DoubleLeftArrow = "⇐";
|
||
var DoubleLeftRightArrow = "⇔";
|
||
var DoubleLeftTee = "⫤";
|
||
var DoubleLongLeftArrow = "⟸";
|
||
var DoubleLongLeftRightArrow = "⟺";
|
||
var DoubleLongRightArrow = "⟹";
|
||
var DoubleRightArrow = "⇒";
|
||
var DoubleRightTee = "⊨";
|
||
var DoubleUpArrow = "⇑";
|
||
var DoubleUpDownArrow = "⇕";
|
||
var DoubleVerticalBar = "∥";
|
||
var DownArrowBar = "⤓";
|
||
var downarrow = "↓";
|
||
var DownArrow = "↓";
|
||
var Downarrow = "⇓";
|
||
var DownArrowUpArrow = "⇵";
|
||
var DownBreve = "̑";
|
||
var downdownarrows = "⇊";
|
||
var downharpoonleft = "⇃";
|
||
var downharpoonright = "⇂";
|
||
var DownLeftRightVector = "⥐";
|
||
var DownLeftTeeVector = "⥞";
|
||
var DownLeftVectorBar = "⥖";
|
||
var DownLeftVector = "↽";
|
||
var DownRightTeeVector = "⥟";
|
||
var DownRightVectorBar = "⥗";
|
||
var DownRightVector = "⇁";
|
||
var DownTeeArrow = "↧";
|
||
var DownTee = "⊤";
|
||
var drbkarow = "⤐";
|
||
var drcorn = "⌟";
|
||
var drcrop = "⌌";
|
||
var Dscr = "𝒟";
|
||
var dscr = "𝒹";
|
||
var DScy = "Ѕ";
|
||
var dscy = "ѕ";
|
||
var dsol = "⧶";
|
||
var Dstrok = "Đ";
|
||
var dstrok = "đ";
|
||
var dtdot = "⋱";
|
||
var dtri = "▿";
|
||
var dtrif = "▾";
|
||
var duarr = "⇵";
|
||
var duhar = "⥯";
|
||
var dwangle = "⦦";
|
||
var DZcy = "Џ";
|
||
var dzcy = "џ";
|
||
var dzigrarr = "⟿";
|
||
var Eacute = "É";
|
||
var eacute = "é";
|
||
var easter = "⩮";
|
||
var Ecaron = "Ě";
|
||
var ecaron = "ě";
|
||
var Ecirc = "Ê";
|
||
var ecirc = "ê";
|
||
var ecir = "≖";
|
||
var ecolon = "≕";
|
||
var Ecy = "Э";
|
||
var ecy = "э";
|
||
var eDDot = "⩷";
|
||
var Edot = "Ė";
|
||
var edot = "ė";
|
||
var eDot = "≑";
|
||
var ee = "ⅇ";
|
||
var efDot = "≒";
|
||
var Efr = "𝔈";
|
||
var efr = "𝔢";
|
||
var eg = "⪚";
|
||
var Egrave = "È";
|
||
var egrave = "è";
|
||
var egs = "⪖";
|
||
var egsdot = "⪘";
|
||
var el = "⪙";
|
||
var Element = "∈";
|
||
var elinters = "⏧";
|
||
var ell = "ℓ";
|
||
var els = "⪕";
|
||
var elsdot = "⪗";
|
||
var Emacr = "Ē";
|
||
var emacr = "ē";
|
||
var empty = "∅";
|
||
var emptyset = "∅";
|
||
var EmptySmallSquare = "◻";
|
||
var emptyv = "∅";
|
||
var EmptyVerySmallSquare = "▫";
|
||
var emsp13 = " ";
|
||
var emsp14 = " ";
|
||
var emsp = " ";
|
||
var ENG = "Ŋ";
|
||
var eng = "ŋ";
|
||
var ensp = " ";
|
||
var Eogon = "Ę";
|
||
var eogon = "ę";
|
||
var Eopf = "𝔼";
|
||
var eopf = "𝕖";
|
||
var epar = "⋕";
|
||
var eparsl = "⧣";
|
||
var eplus = "⩱";
|
||
var epsi = "ε";
|
||
var Epsilon = "Ε";
|
||
var epsilon = "ε";
|
||
var epsiv = "ϵ";
|
||
var eqcirc = "≖";
|
||
var eqcolon = "≕";
|
||
var eqsim = "≂";
|
||
var eqslantgtr = "⪖";
|
||
var eqslantless = "⪕";
|
||
var Equal = "⩵";
|
||
var equals = "=";
|
||
var EqualTilde = "≂";
|
||
var equest = "≟";
|
||
var Equilibrium = "⇌";
|
||
var equiv = "≡";
|
||
var equivDD = "⩸";
|
||
var eqvparsl = "⧥";
|
||
var erarr = "⥱";
|
||
var erDot = "≓";
|
||
var escr = "ℯ";
|
||
var Escr = "ℰ";
|
||
var esdot = "≐";
|
||
var Esim = "⩳";
|
||
var esim = "≂";
|
||
var Eta = "Η";
|
||
var eta = "η";
|
||
var ETH = "Ð";
|
||
var eth = "ð";
|
||
var Euml = "Ë";
|
||
var euml = "ë";
|
||
var euro = "€";
|
||
var excl = "!";
|
||
var exist = "∃";
|
||
var Exists = "∃";
|
||
var expectation = "ℰ";
|
||
var exponentiale = "ⅇ";
|
||
var ExponentialE = "ⅇ";
|
||
var fallingdotseq = "≒";
|
||
var Fcy = "Ф";
|
||
var fcy = "ф";
|
||
var female = "♀";
|
||
var ffilig = "ffi";
|
||
var fflig = "ff";
|
||
var ffllig = "ffl";
|
||
var Ffr = "𝔉";
|
||
var ffr = "𝔣";
|
||
var filig = "fi";
|
||
var FilledSmallSquare = "◼";
|
||
var FilledVerySmallSquare = "▪";
|
||
var fjlig = "fj";
|
||
var flat = "♭";
|
||
var fllig = "fl";
|
||
var fltns = "▱";
|
||
var fnof = "ƒ";
|
||
var Fopf = "𝔽";
|
||
var fopf = "𝕗";
|
||
var forall = "∀";
|
||
var ForAll = "∀";
|
||
var fork = "⋔";
|
||
var forkv = "⫙";
|
||
var Fouriertrf = "ℱ";
|
||
var fpartint = "⨍";
|
||
var frac12 = "½";
|
||
var frac13 = "⅓";
|
||
var frac14 = "¼";
|
||
var frac15 = "⅕";
|
||
var frac16 = "⅙";
|
||
var frac18 = "⅛";
|
||
var frac23 = "⅔";
|
||
var frac25 = "⅖";
|
||
var frac34 = "¾";
|
||
var frac35 = "⅗";
|
||
var frac38 = "⅜";
|
||
var frac45 = "⅘";
|
||
var frac56 = "⅚";
|
||
var frac58 = "⅝";
|
||
var frac78 = "⅞";
|
||
var frasl = "⁄";
|
||
var frown = "⌢";
|
||
var fscr = "𝒻";
|
||
var Fscr = "ℱ";
|
||
var gacute = "ǵ";
|
||
var Gamma = "Γ";
|
||
var gamma = "γ";
|
||
var Gammad = "Ϝ";
|
||
var gammad = "ϝ";
|
||
var gap = "⪆";
|
||
var Gbreve = "Ğ";
|
||
var gbreve = "ğ";
|
||
var Gcedil = "Ģ";
|
||
var Gcirc = "Ĝ";
|
||
var gcirc = "ĝ";
|
||
var Gcy = "Г";
|
||
var gcy = "г";
|
||
var Gdot = "Ġ";
|
||
var gdot = "ġ";
|
||
var ge = "≥";
|
||
var gE = "≧";
|
||
var gEl = "⪌";
|
||
var gel = "⋛";
|
||
var geq = "≥";
|
||
var geqq = "≧";
|
||
var geqslant = "⩾";
|
||
var gescc = "⪩";
|
||
var ges = "⩾";
|
||
var gesdot = "⪀";
|
||
var gesdoto = "⪂";
|
||
var gesdotol = "⪄";
|
||
var gesl = "⋛︀";
|
||
var gesles = "⪔";
|
||
var Gfr = "𝔊";
|
||
var gfr = "𝔤";
|
||
var gg = "≫";
|
||
var Gg = "⋙";
|
||
var ggg = "⋙";
|
||
var gimel = "ℷ";
|
||
var GJcy = "Ѓ";
|
||
var gjcy = "ѓ";
|
||
var gla = "⪥";
|
||
var gl = "≷";
|
||
var glE = "⪒";
|
||
var glj = "⪤";
|
||
var gnap = "⪊";
|
||
var gnapprox = "⪊";
|
||
var gne = "⪈";
|
||
var gnE = "≩";
|
||
var gneq = "⪈";
|
||
var gneqq = "≩";
|
||
var gnsim = "⋧";
|
||
var Gopf = "𝔾";
|
||
var gopf = "𝕘";
|
||
var grave = "`";
|
||
var GreaterEqual = "≥";
|
||
var GreaterEqualLess = "⋛";
|
||
var GreaterFullEqual = "≧";
|
||
var GreaterGreater = "⪢";
|
||
var GreaterLess = "≷";
|
||
var GreaterSlantEqual = "⩾";
|
||
var GreaterTilde = "≳";
|
||
var Gscr = "𝒢";
|
||
var gscr = "ℊ";
|
||
var gsim = "≳";
|
||
var gsime = "⪎";
|
||
var gsiml = "⪐";
|
||
var gtcc = "⪧";
|
||
var gtcir = "⩺";
|
||
var gt = ">";
|
||
var GT = ">";
|
||
var Gt = "≫";
|
||
var gtdot = "⋗";
|
||
var gtlPar = "⦕";
|
||
var gtquest = "⩼";
|
||
var gtrapprox = "⪆";
|
||
var gtrarr = "⥸";
|
||
var gtrdot = "⋗";
|
||
var gtreqless = "⋛";
|
||
var gtreqqless = "⪌";
|
||
var gtrless = "≷";
|
||
var gtrsim = "≳";
|
||
var gvertneqq = "≩︀";
|
||
var gvnE = "≩︀";
|
||
var Hacek = "ˇ";
|
||
var hairsp = " ";
|
||
var half = "½";
|
||
var hamilt = "ℋ";
|
||
var HARDcy = "Ъ";
|
||
var hardcy = "ъ";
|
||
var harrcir = "⥈";
|
||
var harr = "↔";
|
||
var hArr = "⇔";
|
||
var harrw = "↭";
|
||
var Hat = "^";
|
||
var hbar = "ℏ";
|
||
var Hcirc = "Ĥ";
|
||
var hcirc = "ĥ";
|
||
var hearts = "♥";
|
||
var heartsuit = "♥";
|
||
var hellip = "…";
|
||
var hercon = "⊹";
|
||
var hfr = "𝔥";
|
||
var Hfr = "ℌ";
|
||
var HilbertSpace = "ℋ";
|
||
var hksearow = "⤥";
|
||
var hkswarow = "⤦";
|
||
var hoarr = "⇿";
|
||
var homtht = "∻";
|
||
var hookleftarrow = "↩";
|
||
var hookrightarrow = "↪";
|
||
var hopf = "𝕙";
|
||
var Hopf = "ℍ";
|
||
var horbar = "―";
|
||
var HorizontalLine = "─";
|
||
var hscr = "𝒽";
|
||
var Hscr = "ℋ";
|
||
var hslash = "ℏ";
|
||
var Hstrok = "Ħ";
|
||
var hstrok = "ħ";
|
||
var HumpDownHump = "≎";
|
||
var HumpEqual = "≏";
|
||
var hybull = "⁃";
|
||
var hyphen = "‐";
|
||
var Iacute = "Í";
|
||
var iacute = "í";
|
||
var ic = "";
|
||
var Icirc = "Î";
|
||
var icirc = "î";
|
||
var Icy = "И";
|
||
var icy = "и";
|
||
var Idot = "İ";
|
||
var IEcy = "Е";
|
||
var iecy = "е";
|
||
var iexcl = "¡";
|
||
var iff = "⇔";
|
||
var ifr = "𝔦";
|
||
var Ifr = "ℑ";
|
||
var Igrave = "Ì";
|
||
var igrave = "ì";
|
||
var ii = "ⅈ";
|
||
var iiiint = "⨌";
|
||
var iiint = "∭";
|
||
var iinfin = "⧜";
|
||
var iiota = "℩";
|
||
var IJlig = "IJ";
|
||
var ijlig = "ij";
|
||
var Imacr = "Ī";
|
||
var imacr = "ī";
|
||
var image$1 = "ℑ";
|
||
var ImaginaryI = "ⅈ";
|
||
var imagline = "ℐ";
|
||
var imagpart = "ℑ";
|
||
var imath = "ı";
|
||
var Im = "ℑ";
|
||
var imof = "⊷";
|
||
var imped = "Ƶ";
|
||
var Implies = "⇒";
|
||
var incare = "℅";
|
||
var infin = "∞";
|
||
var infintie = "⧝";
|
||
var inodot = "ı";
|
||
var intcal = "⊺";
|
||
var int = "∫";
|
||
var Int = "∬";
|
||
var integers = "ℤ";
|
||
var Integral = "∫";
|
||
var intercal = "⊺";
|
||
var Intersection = "⋂";
|
||
var intlarhk = "⨗";
|
||
var intprod = "⨼";
|
||
var InvisibleComma = "";
|
||
var InvisibleTimes = "";
|
||
var IOcy = "Ё";
|
||
var iocy = "ё";
|
||
var Iogon = "Į";
|
||
var iogon = "į";
|
||
var Iopf = "𝕀";
|
||
var iopf = "𝕚";
|
||
var Iota = "Ι";
|
||
var iota = "ι";
|
||
var iprod = "⨼";
|
||
var iquest = "¿";
|
||
var iscr = "𝒾";
|
||
var Iscr = "ℐ";
|
||
var isin = "∈";
|
||
var isindot = "⋵";
|
||
var isinE = "⋹";
|
||
var isins = "⋴";
|
||
var isinsv = "⋳";
|
||
var isinv = "∈";
|
||
var it = "";
|
||
var Itilde = "Ĩ";
|
||
var itilde = "ĩ";
|
||
var Iukcy = "І";
|
||
var iukcy = "і";
|
||
var Iuml = "Ï";
|
||
var iuml = "ï";
|
||
var Jcirc = "Ĵ";
|
||
var jcirc = "ĵ";
|
||
var Jcy = "Й";
|
||
var jcy = "й";
|
||
var Jfr = "𝔍";
|
||
var jfr = "𝔧";
|
||
var jmath = "ȷ";
|
||
var Jopf = "𝕁";
|
||
var jopf = "𝕛";
|
||
var Jscr = "𝒥";
|
||
var jscr = "𝒿";
|
||
var Jsercy = "Ј";
|
||
var jsercy = "ј";
|
||
var Jukcy = "Є";
|
||
var jukcy = "є";
|
||
var Kappa = "Κ";
|
||
var kappa = "κ";
|
||
var kappav = "ϰ";
|
||
var Kcedil = "Ķ";
|
||
var kcedil = "ķ";
|
||
var Kcy = "К";
|
||
var kcy = "к";
|
||
var Kfr = "𝔎";
|
||
var kfr = "𝔨";
|
||
var kgreen = "ĸ";
|
||
var KHcy = "Х";
|
||
var khcy = "х";
|
||
var KJcy = "Ќ";
|
||
var kjcy = "ќ";
|
||
var Kopf = "𝕂";
|
||
var kopf = "𝕜";
|
||
var Kscr = "𝒦";
|
||
var kscr = "𝓀";
|
||
var lAarr = "⇚";
|
||
var Lacute = "Ĺ";
|
||
var lacute = "ĺ";
|
||
var laemptyv = "⦴";
|
||
var lagran = "ℒ";
|
||
var Lambda = "Λ";
|
||
var lambda = "λ";
|
||
var lang = "⟨";
|
||
var Lang = "⟪";
|
||
var langd = "⦑";
|
||
var langle = "⟨";
|
||
var lap = "⪅";
|
||
var Laplacetrf = "ℒ";
|
||
var laquo = "«";
|
||
var larrb = "⇤";
|
||
var larrbfs = "⤟";
|
||
var larr = "←";
|
||
var Larr = "↞";
|
||
var lArr = "⇐";
|
||
var larrfs = "⤝";
|
||
var larrhk = "↩";
|
||
var larrlp = "↫";
|
||
var larrpl = "⤹";
|
||
var larrsim = "⥳";
|
||
var larrtl = "↢";
|
||
var latail = "⤙";
|
||
var lAtail = "⤛";
|
||
var lat = "⪫";
|
||
var late = "⪭";
|
||
var lates = "⪭︀";
|
||
var lbarr = "⤌";
|
||
var lBarr = "⤎";
|
||
var lbbrk = "❲";
|
||
var lbrace = "{";
|
||
var lbrack = "[";
|
||
var lbrke = "⦋";
|
||
var lbrksld = "⦏";
|
||
var lbrkslu = "⦍";
|
||
var Lcaron = "Ľ";
|
||
var lcaron = "ľ";
|
||
var Lcedil = "Ļ";
|
||
var lcedil = "ļ";
|
||
var lceil = "⌈";
|
||
var lcub = "{";
|
||
var Lcy = "Л";
|
||
var lcy = "л";
|
||
var ldca = "⤶";
|
||
var ldquo = "“";
|
||
var ldquor = "„";
|
||
var ldrdhar = "⥧";
|
||
var ldrushar = "⥋";
|
||
var ldsh = "↲";
|
||
var le = "≤";
|
||
var lE = "≦";
|
||
var LeftAngleBracket = "⟨";
|
||
var LeftArrowBar = "⇤";
|
||
var leftarrow = "←";
|
||
var LeftArrow = "←";
|
||
var Leftarrow = "⇐";
|
||
var LeftArrowRightArrow = "⇆";
|
||
var leftarrowtail = "↢";
|
||
var LeftCeiling = "⌈";
|
||
var LeftDoubleBracket = "⟦";
|
||
var LeftDownTeeVector = "⥡";
|
||
var LeftDownVectorBar = "⥙";
|
||
var LeftDownVector = "⇃";
|
||
var LeftFloor = "⌊";
|
||
var leftharpoondown = "↽";
|
||
var leftharpoonup = "↼";
|
||
var leftleftarrows = "⇇";
|
||
var leftrightarrow = "↔";
|
||
var LeftRightArrow = "↔";
|
||
var Leftrightarrow = "⇔";
|
||
var leftrightarrows = "⇆";
|
||
var leftrightharpoons = "⇋";
|
||
var leftrightsquigarrow = "↭";
|
||
var LeftRightVector = "⥎";
|
||
var LeftTeeArrow = "↤";
|
||
var LeftTee = "⊣";
|
||
var LeftTeeVector = "⥚";
|
||
var leftthreetimes = "⋋";
|
||
var LeftTriangleBar = "⧏";
|
||
var LeftTriangle = "⊲";
|
||
var LeftTriangleEqual = "⊴";
|
||
var LeftUpDownVector = "⥑";
|
||
var LeftUpTeeVector = "⥠";
|
||
var LeftUpVectorBar = "⥘";
|
||
var LeftUpVector = "↿";
|
||
var LeftVectorBar = "⥒";
|
||
var LeftVector = "↼";
|
||
var lEg = "⪋";
|
||
var leg = "⋚";
|
||
var leq = "≤";
|
||
var leqq = "≦";
|
||
var leqslant = "⩽";
|
||
var lescc = "⪨";
|
||
var les = "⩽";
|
||
var lesdot = "⩿";
|
||
var lesdoto = "⪁";
|
||
var lesdotor = "⪃";
|
||
var lesg = "⋚︀";
|
||
var lesges = "⪓";
|
||
var lessapprox = "⪅";
|
||
var lessdot = "⋖";
|
||
var lesseqgtr = "⋚";
|
||
var lesseqqgtr = "⪋";
|
||
var LessEqualGreater = "⋚";
|
||
var LessFullEqual = "≦";
|
||
var LessGreater = "≶";
|
||
var lessgtr = "≶";
|
||
var LessLess = "⪡";
|
||
var lesssim = "≲";
|
||
var LessSlantEqual = "⩽";
|
||
var LessTilde = "≲";
|
||
var lfisht = "⥼";
|
||
var lfloor = "⌊";
|
||
var Lfr = "𝔏";
|
||
var lfr = "𝔩";
|
||
var lg = "≶";
|
||
var lgE = "⪑";
|
||
var lHar = "⥢";
|
||
var lhard = "↽";
|
||
var lharu = "↼";
|
||
var lharul = "⥪";
|
||
var lhblk = "▄";
|
||
var LJcy = "Љ";
|
||
var ljcy = "љ";
|
||
var llarr = "⇇";
|
||
var ll = "≪";
|
||
var Ll = "⋘";
|
||
var llcorner = "⌞";
|
||
var Lleftarrow = "⇚";
|
||
var llhard = "⥫";
|
||
var lltri = "◺";
|
||
var Lmidot = "Ŀ";
|
||
var lmidot = "ŀ";
|
||
var lmoustache = "⎰";
|
||
var lmoust = "⎰";
|
||
var lnap = "⪉";
|
||
var lnapprox = "⪉";
|
||
var lne = "⪇";
|
||
var lnE = "≨";
|
||
var lneq = "⪇";
|
||
var lneqq = "≨";
|
||
var lnsim = "⋦";
|
||
var loang = "⟬";
|
||
var loarr = "⇽";
|
||
var lobrk = "⟦";
|
||
var longleftarrow = "⟵";
|
||
var LongLeftArrow = "⟵";
|
||
var Longleftarrow = "⟸";
|
||
var longleftrightarrow = "⟷";
|
||
var LongLeftRightArrow = "⟷";
|
||
var Longleftrightarrow = "⟺";
|
||
var longmapsto = "⟼";
|
||
var longrightarrow = "⟶";
|
||
var LongRightArrow = "⟶";
|
||
var Longrightarrow = "⟹";
|
||
var looparrowleft = "↫";
|
||
var looparrowright = "↬";
|
||
var lopar = "⦅";
|
||
var Lopf = "𝕃";
|
||
var lopf = "𝕝";
|
||
var loplus = "⨭";
|
||
var lotimes = "⨴";
|
||
var lowast = "∗";
|
||
var lowbar = "_";
|
||
var LowerLeftArrow = "↙";
|
||
var LowerRightArrow = "↘";
|
||
var loz = "◊";
|
||
var lozenge = "◊";
|
||
var lozf = "⧫";
|
||
var lpar = "(";
|
||
var lparlt = "⦓";
|
||
var lrarr = "⇆";
|
||
var lrcorner = "⌟";
|
||
var lrhar = "⇋";
|
||
var lrhard = "⥭";
|
||
var lrm = "";
|
||
var lrtri = "⊿";
|
||
var lsaquo = "‹";
|
||
var lscr = "𝓁";
|
||
var Lscr = "ℒ";
|
||
var lsh = "↰";
|
||
var Lsh = "↰";
|
||
var lsim = "≲";
|
||
var lsime = "⪍";
|
||
var lsimg = "⪏";
|
||
var lsqb = "[";
|
||
var lsquo = "‘";
|
||
var lsquor = "‚";
|
||
var Lstrok = "Ł";
|
||
var lstrok = "ł";
|
||
var ltcc = "⪦";
|
||
var ltcir = "⩹";
|
||
var lt = "<";
|
||
var LT = "<";
|
||
var Lt = "≪";
|
||
var ltdot = "⋖";
|
||
var lthree = "⋋";
|
||
var ltimes = "⋉";
|
||
var ltlarr = "⥶";
|
||
var ltquest = "⩻";
|
||
var ltri = "◃";
|
||
var ltrie = "⊴";
|
||
var ltrif = "◂";
|
||
var ltrPar = "⦖";
|
||
var lurdshar = "⥊";
|
||
var luruhar = "⥦";
|
||
var lvertneqq = "≨︀";
|
||
var lvnE = "≨︀";
|
||
var macr = "¯";
|
||
var male = "♂";
|
||
var malt = "✠";
|
||
var maltese = "✠";
|
||
var map$1 = "↦";
|
||
var mapsto = "↦";
|
||
var mapstodown = "↧";
|
||
var mapstoleft = "↤";
|
||
var mapstoup = "↥";
|
||
var marker = "▮";
|
||
var mcomma = "⨩";
|
||
var Mcy = "М";
|
||
var mcy = "м";
|
||
var mdash = "—";
|
||
var mDDot = "∺";
|
||
var measuredangle = "∡";
|
||
var MediumSpace = " ";
|
||
var Mellintrf = "ℳ";
|
||
var Mfr = "𝔐";
|
||
var mfr = "𝔪";
|
||
var mho = "℧";
|
||
var micro = "µ";
|
||
var midast = "*";
|
||
var midcir = "⫰";
|
||
var mid = "∣";
|
||
var middot = "·";
|
||
var minusb = "⊟";
|
||
var minus = "−";
|
||
var minusd = "∸";
|
||
var minusdu = "⨪";
|
||
var MinusPlus = "∓";
|
||
var mlcp = "⫛";
|
||
var mldr = "…";
|
||
var mnplus = "∓";
|
||
var models = "⊧";
|
||
var Mopf = "𝕄";
|
||
var mopf = "𝕞";
|
||
var mp = "∓";
|
||
var mscr = "𝓂";
|
||
var Mscr = "ℳ";
|
||
var mstpos = "∾";
|
||
var Mu = "Μ";
|
||
var mu = "μ";
|
||
var multimap = "⊸";
|
||
var mumap = "⊸";
|
||
var nabla = "∇";
|
||
var Nacute = "Ń";
|
||
var nacute = "ń";
|
||
var nang = "∠⃒";
|
||
var nap = "≉";
|
||
var napE = "⩰̸";
|
||
var napid = "≋̸";
|
||
var napos = "ʼn";
|
||
var napprox = "≉";
|
||
var natural = "♮";
|
||
var naturals = "ℕ";
|
||
var natur = "♮";
|
||
var nbsp = " ";
|
||
var nbump = "≎̸";
|
||
var nbumpe = "≏̸";
|
||
var ncap = "⩃";
|
||
var Ncaron = "Ň";
|
||
var ncaron = "ň";
|
||
var Ncedil = "Ņ";
|
||
var ncedil = "ņ";
|
||
var ncong = "≇";
|
||
var ncongdot = "⩭̸";
|
||
var ncup = "⩂";
|
||
var Ncy = "Н";
|
||
var ncy = "н";
|
||
var ndash = "–";
|
||
var nearhk = "⤤";
|
||
var nearr = "↗";
|
||
var neArr = "⇗";
|
||
var nearrow = "↗";
|
||
var ne = "≠";
|
||
var nedot = "≐̸";
|
||
var NegativeMediumSpace = "";
|
||
var NegativeThickSpace = "";
|
||
var NegativeThinSpace = "";
|
||
var NegativeVeryThinSpace = "";
|
||
var nequiv = "≢";
|
||
var nesear = "⤨";
|
||
var nesim = "≂̸";
|
||
var NestedGreaterGreater = "≫";
|
||
var NestedLessLess = "≪";
|
||
var NewLine = "\n";
|
||
var nexist = "∄";
|
||
var nexists = "∄";
|
||
var Nfr = "𝔑";
|
||
var nfr = "𝔫";
|
||
var ngE = "≧̸";
|
||
var nge = "≱";
|
||
var ngeq = "≱";
|
||
var ngeqq = "≧̸";
|
||
var ngeqslant = "⩾̸";
|
||
var nges = "⩾̸";
|
||
var nGg = "⋙̸";
|
||
var ngsim = "≵";
|
||
var nGt = "≫⃒";
|
||
var ngt = "≯";
|
||
var ngtr = "≯";
|
||
var nGtv = "≫̸";
|
||
var nharr = "↮";
|
||
var nhArr = "⇎";
|
||
var nhpar = "⫲";
|
||
var ni = "∋";
|
||
var nis = "⋼";
|
||
var nisd = "⋺";
|
||
var niv = "∋";
|
||
var NJcy = "Њ";
|
||
var njcy = "њ";
|
||
var nlarr = "↚";
|
||
var nlArr = "⇍";
|
||
var nldr = "‥";
|
||
var nlE = "≦̸";
|
||
var nle = "≰";
|
||
var nleftarrow = "↚";
|
||
var nLeftarrow = "⇍";
|
||
var nleftrightarrow = "↮";
|
||
var nLeftrightarrow = "⇎";
|
||
var nleq = "≰";
|
||
var nleqq = "≦̸";
|
||
var nleqslant = "⩽̸";
|
||
var nles = "⩽̸";
|
||
var nless = "≮";
|
||
var nLl = "⋘̸";
|
||
var nlsim = "≴";
|
||
var nLt = "≪⃒";
|
||
var nlt = "≮";
|
||
var nltri = "⋪";
|
||
var nltrie = "⋬";
|
||
var nLtv = "≪̸";
|
||
var nmid = "∤";
|
||
var NoBreak = "";
|
||
var NonBreakingSpace = " ";
|
||
var nopf = "𝕟";
|
||
var Nopf = "ℕ";
|
||
var Not = "⫬";
|
||
var not = "¬";
|
||
var NotCongruent = "≢";
|
||
var NotCupCap = "≭";
|
||
var NotDoubleVerticalBar = "∦";
|
||
var NotElement = "∉";
|
||
var NotEqual = "≠";
|
||
var NotEqualTilde = "≂̸";
|
||
var NotExists = "∄";
|
||
var NotGreater = "≯";
|
||
var NotGreaterEqual = "≱";
|
||
var NotGreaterFullEqual = "≧̸";
|
||
var NotGreaterGreater = "≫̸";
|
||
var NotGreaterLess = "≹";
|
||
var NotGreaterSlantEqual = "⩾̸";
|
||
var NotGreaterTilde = "≵";
|
||
var NotHumpDownHump = "≎̸";
|
||
var NotHumpEqual = "≏̸";
|
||
var notin = "∉";
|
||
var notindot = "⋵̸";
|
||
var notinE = "⋹̸";
|
||
var notinva = "∉";
|
||
var notinvb = "⋷";
|
||
var notinvc = "⋶";
|
||
var NotLeftTriangleBar = "⧏̸";
|
||
var NotLeftTriangle = "⋪";
|
||
var NotLeftTriangleEqual = "⋬";
|
||
var NotLess = "≮";
|
||
var NotLessEqual = "≰";
|
||
var NotLessGreater = "≸";
|
||
var NotLessLess = "≪̸";
|
||
var NotLessSlantEqual = "⩽̸";
|
||
var NotLessTilde = "≴";
|
||
var NotNestedGreaterGreater = "⪢̸";
|
||
var NotNestedLessLess = "⪡̸";
|
||
var notni = "∌";
|
||
var notniva = "∌";
|
||
var notnivb = "⋾";
|
||
var notnivc = "⋽";
|
||
var NotPrecedes = "⊀";
|
||
var NotPrecedesEqual = "⪯̸";
|
||
var NotPrecedesSlantEqual = "⋠";
|
||
var NotReverseElement = "∌";
|
||
var NotRightTriangleBar = "⧐̸";
|
||
var NotRightTriangle = "⋫";
|
||
var NotRightTriangleEqual = "⋭";
|
||
var NotSquareSubset = "⊏̸";
|
||
var NotSquareSubsetEqual = "⋢";
|
||
var NotSquareSuperset = "⊐̸";
|
||
var NotSquareSupersetEqual = "⋣";
|
||
var NotSubset = "⊂⃒";
|
||
var NotSubsetEqual = "⊈";
|
||
var NotSucceeds = "⊁";
|
||
var NotSucceedsEqual = "⪰̸";
|
||
var NotSucceedsSlantEqual = "⋡";
|
||
var NotSucceedsTilde = "≿̸";
|
||
var NotSuperset = "⊃⃒";
|
||
var NotSupersetEqual = "⊉";
|
||
var NotTilde = "≁";
|
||
var NotTildeEqual = "≄";
|
||
var NotTildeFullEqual = "≇";
|
||
var NotTildeTilde = "≉";
|
||
var NotVerticalBar = "∤";
|
||
var nparallel = "∦";
|
||
var npar = "∦";
|
||
var nparsl = "⫽⃥";
|
||
var npart = "∂̸";
|
||
var npolint = "⨔";
|
||
var npr = "⊀";
|
||
var nprcue = "⋠";
|
||
var nprec = "⊀";
|
||
var npreceq = "⪯̸";
|
||
var npre = "⪯̸";
|
||
var nrarrc = "⤳̸";
|
||
var nrarr = "↛";
|
||
var nrArr = "⇏";
|
||
var nrarrw = "↝̸";
|
||
var nrightarrow = "↛";
|
||
var nRightarrow = "⇏";
|
||
var nrtri = "⋫";
|
||
var nrtrie = "⋭";
|
||
var nsc = "⊁";
|
||
var nsccue = "⋡";
|
||
var nsce = "⪰̸";
|
||
var Nscr = "𝒩";
|
||
var nscr = "𝓃";
|
||
var nshortmid = "∤";
|
||
var nshortparallel = "∦";
|
||
var nsim = "≁";
|
||
var nsime = "≄";
|
||
var nsimeq = "≄";
|
||
var nsmid = "∤";
|
||
var nspar = "∦";
|
||
var nsqsube = "⋢";
|
||
var nsqsupe = "⋣";
|
||
var nsub = "⊄";
|
||
var nsubE = "⫅̸";
|
||
var nsube = "⊈";
|
||
var nsubset = "⊂⃒";
|
||
var nsubseteq = "⊈";
|
||
var nsubseteqq = "⫅̸";
|
||
var nsucc = "⊁";
|
||
var nsucceq = "⪰̸";
|
||
var nsup = "⊅";
|
||
var nsupE = "⫆̸";
|
||
var nsupe = "⊉";
|
||
var nsupset = "⊃⃒";
|
||
var nsupseteq = "⊉";
|
||
var nsupseteqq = "⫆̸";
|
||
var ntgl = "≹";
|
||
var Ntilde = "Ñ";
|
||
var ntilde = "ñ";
|
||
var ntlg = "≸";
|
||
var ntriangleleft = "⋪";
|
||
var ntrianglelefteq = "⋬";
|
||
var ntriangleright = "⋫";
|
||
var ntrianglerighteq = "⋭";
|
||
var Nu = "Ν";
|
||
var nu = "ν";
|
||
var num = "#";
|
||
var numero = "№";
|
||
var numsp = " ";
|
||
var nvap = "≍⃒";
|
||
var nvdash = "⊬";
|
||
var nvDash = "⊭";
|
||
var nVdash = "⊮";
|
||
var nVDash = "⊯";
|
||
var nvge = "≥⃒";
|
||
var nvgt = ">⃒";
|
||
var nvHarr = "⤄";
|
||
var nvinfin = "⧞";
|
||
var nvlArr = "⤂";
|
||
var nvle = "≤⃒";
|
||
var nvlt = "<⃒";
|
||
var nvltrie = "⊴⃒";
|
||
var nvrArr = "⤃";
|
||
var nvrtrie = "⊵⃒";
|
||
var nvsim = "∼⃒";
|
||
var nwarhk = "⤣";
|
||
var nwarr = "↖";
|
||
var nwArr = "⇖";
|
||
var nwarrow = "↖";
|
||
var nwnear = "⤧";
|
||
var Oacute = "Ó";
|
||
var oacute = "ó";
|
||
var oast = "⊛";
|
||
var Ocirc = "Ô";
|
||
var ocirc = "ô";
|
||
var ocir = "⊚";
|
||
var Ocy = "О";
|
||
var ocy = "о";
|
||
var odash = "⊝";
|
||
var Odblac = "Ő";
|
||
var odblac = "ő";
|
||
var odiv = "⨸";
|
||
var odot = "⊙";
|
||
var odsold = "⦼";
|
||
var OElig = "Œ";
|
||
var oelig = "œ";
|
||
var ofcir = "⦿";
|
||
var Ofr = "𝔒";
|
||
var ofr = "𝔬";
|
||
var ogon = "˛";
|
||
var Ograve = "Ò";
|
||
var ograve = "ò";
|
||
var ogt = "⧁";
|
||
var ohbar = "⦵";
|
||
var ohm = "Ω";
|
||
var oint = "∮";
|
||
var olarr = "↺";
|
||
var olcir = "⦾";
|
||
var olcross = "⦻";
|
||
var oline = "‾";
|
||
var olt = "⧀";
|
||
var Omacr = "Ō";
|
||
var omacr = "ō";
|
||
var Omega = "Ω";
|
||
var omega = "ω";
|
||
var Omicron = "Ο";
|
||
var omicron = "ο";
|
||
var omid = "⦶";
|
||
var ominus = "⊖";
|
||
var Oopf = "𝕆";
|
||
var oopf = "𝕠";
|
||
var opar = "⦷";
|
||
var OpenCurlyDoubleQuote = "“";
|
||
var OpenCurlyQuote = "‘";
|
||
var operp = "⦹";
|
||
var oplus = "⊕";
|
||
var orarr = "↻";
|
||
var Or = "⩔";
|
||
var or = "∨";
|
||
var ord = "⩝";
|
||
var order = "ℴ";
|
||
var orderof = "ℴ";
|
||
var ordf = "ª";
|
||
var ordm = "º";
|
||
var origof = "⊶";
|
||
var oror = "⩖";
|
||
var orslope = "⩗";
|
||
var orv = "⩛";
|
||
var oS = "Ⓢ";
|
||
var Oscr = "𝒪";
|
||
var oscr = "ℴ";
|
||
var Oslash = "Ø";
|
||
var oslash = "ø";
|
||
var osol = "⊘";
|
||
var Otilde = "Õ";
|
||
var otilde = "õ";
|
||
var otimesas = "⨶";
|
||
var Otimes = "⨷";
|
||
var otimes = "⊗";
|
||
var Ouml = "Ö";
|
||
var ouml = "ö";
|
||
var ovbar = "⌽";
|
||
var OverBar = "‾";
|
||
var OverBrace = "⏞";
|
||
var OverBracket = "⎴";
|
||
var OverParenthesis = "⏜";
|
||
var para = "¶";
|
||
var parallel = "∥";
|
||
var par = "∥";
|
||
var parsim = "⫳";
|
||
var parsl = "⫽";
|
||
var part = "∂";
|
||
var PartialD = "∂";
|
||
var Pcy = "П";
|
||
var pcy = "п";
|
||
var percnt = "%";
|
||
var period = ".";
|
||
var permil = "‰";
|
||
var perp = "⊥";
|
||
var pertenk = "‱";
|
||
var Pfr = "𝔓";
|
||
var pfr = "𝔭";
|
||
var Phi = "Φ";
|
||
var phi = "φ";
|
||
var phiv = "ϕ";
|
||
var phmmat = "ℳ";
|
||
var phone = "☎";
|
||
var Pi = "Π";
|
||
var pi = "π";
|
||
var pitchfork = "⋔";
|
||
var piv = "ϖ";
|
||
var planck = "ℏ";
|
||
var planckh = "ℎ";
|
||
var plankv = "ℏ";
|
||
var plusacir = "⨣";
|
||
var plusb = "⊞";
|
||
var pluscir = "⨢";
|
||
var plus = "+";
|
||
var plusdo = "∔";
|
||
var plusdu = "⨥";
|
||
var pluse = "⩲";
|
||
var PlusMinus = "±";
|
||
var plusmn = "±";
|
||
var plussim = "⨦";
|
||
var plustwo = "⨧";
|
||
var pm = "±";
|
||
var Poincareplane = "ℌ";
|
||
var pointint = "⨕";
|
||
var popf = "𝕡";
|
||
var Popf = "ℙ";
|
||
var pound = "£";
|
||
var prap = "⪷";
|
||
var Pr = "⪻";
|
||
var pr = "≺";
|
||
var prcue = "≼";
|
||
var precapprox = "⪷";
|
||
var prec = "≺";
|
||
var preccurlyeq = "≼";
|
||
var Precedes = "≺";
|
||
var PrecedesEqual = "⪯";
|
||
var PrecedesSlantEqual = "≼";
|
||
var PrecedesTilde = "≾";
|
||
var preceq = "⪯";
|
||
var precnapprox = "⪹";
|
||
var precneqq = "⪵";
|
||
var precnsim = "⋨";
|
||
var pre = "⪯";
|
||
var prE = "⪳";
|
||
var precsim = "≾";
|
||
var prime = "′";
|
||
var Prime = "″";
|
||
var primes = "ℙ";
|
||
var prnap = "⪹";
|
||
var prnE = "⪵";
|
||
var prnsim = "⋨";
|
||
var prod = "∏";
|
||
var Product = "∏";
|
||
var profalar = "⌮";
|
||
var profline = "⌒";
|
||
var profsurf = "⌓";
|
||
var prop = "∝";
|
||
var Proportional = "∝";
|
||
var Proportion = "∷";
|
||
var propto = "∝";
|
||
var prsim = "≾";
|
||
var prurel = "⊰";
|
||
var Pscr = "𝒫";
|
||
var pscr = "𝓅";
|
||
var Psi = "Ψ";
|
||
var psi = "ψ";
|
||
var puncsp = " ";
|
||
var Qfr = "𝔔";
|
||
var qfr = "𝔮";
|
||
var qint = "⨌";
|
||
var qopf = "𝕢";
|
||
var Qopf = "ℚ";
|
||
var qprime = "⁗";
|
||
var Qscr = "𝒬";
|
||
var qscr = "𝓆";
|
||
var quaternions = "ℍ";
|
||
var quatint = "⨖";
|
||
var quest = "?";
|
||
var questeq = "≟";
|
||
var quot = "\"";
|
||
var QUOT = "\"";
|
||
var rAarr = "⇛";
|
||
var race = "∽̱";
|
||
var Racute = "Ŕ";
|
||
var racute = "ŕ";
|
||
var radic = "√";
|
||
var raemptyv = "⦳";
|
||
var rang = "⟩";
|
||
var Rang = "⟫";
|
||
var rangd = "⦒";
|
||
var range = "⦥";
|
||
var rangle = "⟩";
|
||
var raquo = "»";
|
||
var rarrap = "⥵";
|
||
var rarrb = "⇥";
|
||
var rarrbfs = "⤠";
|
||
var rarrc = "⤳";
|
||
var rarr = "→";
|
||
var Rarr = "↠";
|
||
var rArr = "⇒";
|
||
var rarrfs = "⤞";
|
||
var rarrhk = "↪";
|
||
var rarrlp = "↬";
|
||
var rarrpl = "⥅";
|
||
var rarrsim = "⥴";
|
||
var Rarrtl = "⤖";
|
||
var rarrtl = "↣";
|
||
var rarrw = "↝";
|
||
var ratail = "⤚";
|
||
var rAtail = "⤜";
|
||
var ratio = "∶";
|
||
var rationals = "ℚ";
|
||
var rbarr = "⤍";
|
||
var rBarr = "⤏";
|
||
var RBarr = "⤐";
|
||
var rbbrk = "❳";
|
||
var rbrace = "}";
|
||
var rbrack = "]";
|
||
var rbrke = "⦌";
|
||
var rbrksld = "⦎";
|
||
var rbrkslu = "⦐";
|
||
var Rcaron = "Ř";
|
||
var rcaron = "ř";
|
||
var Rcedil = "Ŗ";
|
||
var rcedil = "ŗ";
|
||
var rceil = "⌉";
|
||
var rcub = "}";
|
||
var Rcy = "Р";
|
||
var rcy = "р";
|
||
var rdca = "⤷";
|
||
var rdldhar = "⥩";
|
||
var rdquo = "”";
|
||
var rdquor = "”";
|
||
var rdsh = "↳";
|
||
var real = "ℜ";
|
||
var realine = "ℛ";
|
||
var realpart = "ℜ";
|
||
var reals = "ℝ";
|
||
var Re = "ℜ";
|
||
var rect = "▭";
|
||
var reg = "®";
|
||
var REG = "®";
|
||
var ReverseElement = "∋";
|
||
var ReverseEquilibrium = "⇋";
|
||
var ReverseUpEquilibrium = "⥯";
|
||
var rfisht = "⥽";
|
||
var rfloor = "⌋";
|
||
var rfr = "𝔯";
|
||
var Rfr = "ℜ";
|
||
var rHar = "⥤";
|
||
var rhard = "⇁";
|
||
var rharu = "⇀";
|
||
var rharul = "⥬";
|
||
var Rho = "Ρ";
|
||
var rho = "ρ";
|
||
var rhov = "ϱ";
|
||
var RightAngleBracket = "⟩";
|
||
var RightArrowBar = "⇥";
|
||
var rightarrow = "→";
|
||
var RightArrow = "→";
|
||
var Rightarrow = "⇒";
|
||
var RightArrowLeftArrow = "⇄";
|
||
var rightarrowtail = "↣";
|
||
var RightCeiling = "⌉";
|
||
var RightDoubleBracket = "⟧";
|
||
var RightDownTeeVector = "⥝";
|
||
var RightDownVectorBar = "⥕";
|
||
var RightDownVector = "⇂";
|
||
var RightFloor = "⌋";
|
||
var rightharpoondown = "⇁";
|
||
var rightharpoonup = "⇀";
|
||
var rightleftarrows = "⇄";
|
||
var rightleftharpoons = "⇌";
|
||
var rightrightarrows = "⇉";
|
||
var rightsquigarrow = "↝";
|
||
var RightTeeArrow = "↦";
|
||
var RightTee = "⊢";
|
||
var RightTeeVector = "⥛";
|
||
var rightthreetimes = "⋌";
|
||
var RightTriangleBar = "⧐";
|
||
var RightTriangle = "⊳";
|
||
var RightTriangleEqual = "⊵";
|
||
var RightUpDownVector = "⥏";
|
||
var RightUpTeeVector = "⥜";
|
||
var RightUpVectorBar = "⥔";
|
||
var RightUpVector = "↾";
|
||
var RightVectorBar = "⥓";
|
||
var RightVector = "⇀";
|
||
var ring = "˚";
|
||
var risingdotseq = "≓";
|
||
var rlarr = "⇄";
|
||
var rlhar = "⇌";
|
||
var rlm = "";
|
||
var rmoustache = "⎱";
|
||
var rmoust = "⎱";
|
||
var rnmid = "⫮";
|
||
var roang = "⟭";
|
||
var roarr = "⇾";
|
||
var robrk = "⟧";
|
||
var ropar = "⦆";
|
||
var ropf = "𝕣";
|
||
var Ropf = "ℝ";
|
||
var roplus = "⨮";
|
||
var rotimes = "⨵";
|
||
var RoundImplies = "⥰";
|
||
var rpar = ")";
|
||
var rpargt = "⦔";
|
||
var rppolint = "⨒";
|
||
var rrarr = "⇉";
|
||
var Rrightarrow = "⇛";
|
||
var rsaquo = "›";
|
||
var rscr = "𝓇";
|
||
var Rscr = "ℛ";
|
||
var rsh = "↱";
|
||
var Rsh = "↱";
|
||
var rsqb = "]";
|
||
var rsquo = "’";
|
||
var rsquor = "’";
|
||
var rthree = "⋌";
|
||
var rtimes = "⋊";
|
||
var rtri = "▹";
|
||
var rtrie = "⊵";
|
||
var rtrif = "▸";
|
||
var rtriltri = "⧎";
|
||
var RuleDelayed = "⧴";
|
||
var ruluhar = "⥨";
|
||
var rx = "℞";
|
||
var Sacute = "Ś";
|
||
var sacute = "ś";
|
||
var sbquo = "‚";
|
||
var scap = "⪸";
|
||
var Scaron = "Š";
|
||
var scaron = "š";
|
||
var Sc = "⪼";
|
||
var sc = "≻";
|
||
var sccue = "≽";
|
||
var sce = "⪰";
|
||
var scE = "⪴";
|
||
var Scedil = "Ş";
|
||
var scedil = "ş";
|
||
var Scirc = "Ŝ";
|
||
var scirc = "ŝ";
|
||
var scnap = "⪺";
|
||
var scnE = "⪶";
|
||
var scnsim = "⋩";
|
||
var scpolint = "⨓";
|
||
var scsim = "≿";
|
||
var Scy = "С";
|
||
var scy = "с";
|
||
var sdotb = "⊡";
|
||
var sdot = "⋅";
|
||
var sdote = "⩦";
|
||
var searhk = "⤥";
|
||
var searr = "↘";
|
||
var seArr = "⇘";
|
||
var searrow = "↘";
|
||
var sect = "§";
|
||
var semi = ";";
|
||
var seswar = "⤩";
|
||
var setminus = "∖";
|
||
var setmn = "∖";
|
||
var sext = "✶";
|
||
var Sfr = "𝔖";
|
||
var sfr = "𝔰";
|
||
var sfrown = "⌢";
|
||
var sharp = "♯";
|
||
var SHCHcy = "Щ";
|
||
var shchcy = "щ";
|
||
var SHcy = "Ш";
|
||
var shcy = "ш";
|
||
var ShortDownArrow = "↓";
|
||
var ShortLeftArrow = "←";
|
||
var shortmid = "∣";
|
||
var shortparallel = "∥";
|
||
var ShortRightArrow = "→";
|
||
var ShortUpArrow = "↑";
|
||
var shy = "";
|
||
var Sigma = "Σ";
|
||
var sigma = "σ";
|
||
var sigmaf = "ς";
|
||
var sigmav = "ς";
|
||
var sim = "∼";
|
||
var simdot = "⩪";
|
||
var sime = "≃";
|
||
var simeq = "≃";
|
||
var simg = "⪞";
|
||
var simgE = "⪠";
|
||
var siml = "⪝";
|
||
var simlE = "⪟";
|
||
var simne = "≆";
|
||
var simplus = "⨤";
|
||
var simrarr = "⥲";
|
||
var slarr = "←";
|
||
var SmallCircle = "∘";
|
||
var smallsetminus = "∖";
|
||
var smashp = "⨳";
|
||
var smeparsl = "⧤";
|
||
var smid = "∣";
|
||
var smile = "⌣";
|
||
var smt = "⪪";
|
||
var smte = "⪬";
|
||
var smtes = "⪬︀";
|
||
var SOFTcy = "Ь";
|
||
var softcy = "ь";
|
||
var solbar = "⌿";
|
||
var solb = "⧄";
|
||
var sol = "/";
|
||
var Sopf = "𝕊";
|
||
var sopf = "𝕤";
|
||
var spades = "♠";
|
||
var spadesuit = "♠";
|
||
var spar = "∥";
|
||
var sqcap = "⊓";
|
||
var sqcaps = "⊓︀";
|
||
var sqcup = "⊔";
|
||
var sqcups = "⊔︀";
|
||
var Sqrt = "√";
|
||
var sqsub = "⊏";
|
||
var sqsube = "⊑";
|
||
var sqsubset = "⊏";
|
||
var sqsubseteq = "⊑";
|
||
var sqsup = "⊐";
|
||
var sqsupe = "⊒";
|
||
var sqsupset = "⊐";
|
||
var sqsupseteq = "⊒";
|
||
var square = "□";
|
||
var Square = "□";
|
||
var SquareIntersection = "⊓";
|
||
var SquareSubset = "⊏";
|
||
var SquareSubsetEqual = "⊑";
|
||
var SquareSuperset = "⊐";
|
||
var SquareSupersetEqual = "⊒";
|
||
var SquareUnion = "⊔";
|
||
var squarf = "▪";
|
||
var squ = "□";
|
||
var squf = "▪";
|
||
var srarr = "→";
|
||
var Sscr = "𝒮";
|
||
var sscr = "𝓈";
|
||
var ssetmn = "∖";
|
||
var ssmile = "⌣";
|
||
var sstarf = "⋆";
|
||
var Star = "⋆";
|
||
var star = "☆";
|
||
var starf = "★";
|
||
var straightepsilon = "ϵ";
|
||
var straightphi = "ϕ";
|
||
var strns = "¯";
|
||
var sub = "⊂";
|
||
var Sub = "⋐";
|
||
var subdot = "⪽";
|
||
var subE = "⫅";
|
||
var sube = "⊆";
|
||
var subedot = "⫃";
|
||
var submult = "⫁";
|
||
var subnE = "⫋";
|
||
var subne = "⊊";
|
||
var subplus = "⪿";
|
||
var subrarr = "⥹";
|
||
var subset = "⊂";
|
||
var Subset = "⋐";
|
||
var subseteq = "⊆";
|
||
var subseteqq = "⫅";
|
||
var SubsetEqual = "⊆";
|
||
var subsetneq = "⊊";
|
||
var subsetneqq = "⫋";
|
||
var subsim = "⫇";
|
||
var subsub = "⫕";
|
||
var subsup = "⫓";
|
||
var succapprox = "⪸";
|
||
var succ = "≻";
|
||
var succcurlyeq = "≽";
|
||
var Succeeds = "≻";
|
||
var SucceedsEqual = "⪰";
|
||
var SucceedsSlantEqual = "≽";
|
||
var SucceedsTilde = "≿";
|
||
var succeq = "⪰";
|
||
var succnapprox = "⪺";
|
||
var succneqq = "⪶";
|
||
var succnsim = "⋩";
|
||
var succsim = "≿";
|
||
var SuchThat = "∋";
|
||
var sum = "∑";
|
||
var Sum = "∑";
|
||
var sung = "♪";
|
||
var sup1 = "¹";
|
||
var sup2 = "²";
|
||
var sup3 = "³";
|
||
var sup = "⊃";
|
||
var Sup = "⋑";
|
||
var supdot = "⪾";
|
||
var supdsub = "⫘";
|
||
var supE = "⫆";
|
||
var supe = "⊇";
|
||
var supedot = "⫄";
|
||
var Superset = "⊃";
|
||
var SupersetEqual = "⊇";
|
||
var suphsol = "⟉";
|
||
var suphsub = "⫗";
|
||
var suplarr = "⥻";
|
||
var supmult = "⫂";
|
||
var supnE = "⫌";
|
||
var supne = "⊋";
|
||
var supplus = "⫀";
|
||
var supset = "⊃";
|
||
var Supset = "⋑";
|
||
var supseteq = "⊇";
|
||
var supseteqq = "⫆";
|
||
var supsetneq = "⊋";
|
||
var supsetneqq = "⫌";
|
||
var supsim = "⫈";
|
||
var supsub = "⫔";
|
||
var supsup = "⫖";
|
||
var swarhk = "⤦";
|
||
var swarr = "↙";
|
||
var swArr = "⇙";
|
||
var swarrow = "↙";
|
||
var swnwar = "⤪";
|
||
var szlig = "ß";
|
||
var Tab = "\t";
|
||
var target = "⌖";
|
||
var Tau = "Τ";
|
||
var tau = "τ";
|
||
var tbrk = "⎴";
|
||
var Tcaron = "Ť";
|
||
var tcaron = "ť";
|
||
var Tcedil = "Ţ";
|
||
var tcedil = "ţ";
|
||
var Tcy = "Т";
|
||
var tcy = "т";
|
||
var tdot = "⃛";
|
||
var telrec = "⌕";
|
||
var Tfr = "𝔗";
|
||
var tfr = "𝔱";
|
||
var there4 = "∴";
|
||
var therefore = "∴";
|
||
var Therefore = "∴";
|
||
var Theta = "Θ";
|
||
var theta = "θ";
|
||
var thetasym = "ϑ";
|
||
var thetav = "ϑ";
|
||
var thickapprox = "≈";
|
||
var thicksim = "∼";
|
||
var ThickSpace = " ";
|
||
var ThinSpace = " ";
|
||
var thinsp = " ";
|
||
var thkap = "≈";
|
||
var thksim = "∼";
|
||
var THORN = "Þ";
|
||
var thorn = "þ";
|
||
var tilde = "˜";
|
||
var Tilde = "∼";
|
||
var TildeEqual = "≃";
|
||
var TildeFullEqual = "≅";
|
||
var TildeTilde = "≈";
|
||
var timesbar = "⨱";
|
||
var timesb = "⊠";
|
||
var times = "×";
|
||
var timesd = "⨰";
|
||
var tint = "∭";
|
||
var toea = "⤨";
|
||
var topbot = "⌶";
|
||
var topcir = "⫱";
|
||
var top = "⊤";
|
||
var Topf = "𝕋";
|
||
var topf = "𝕥";
|
||
var topfork = "⫚";
|
||
var tosa = "⤩";
|
||
var tprime = "‴";
|
||
var trade = "™";
|
||
var TRADE = "™";
|
||
var triangle = "▵";
|
||
var triangledown = "▿";
|
||
var triangleleft = "◃";
|
||
var trianglelefteq = "⊴";
|
||
var triangleq = "≜";
|
||
var triangleright = "▹";
|
||
var trianglerighteq = "⊵";
|
||
var tridot = "◬";
|
||
var trie = "≜";
|
||
var triminus = "⨺";
|
||
var TripleDot = "⃛";
|
||
var triplus = "⨹";
|
||
var trisb = "⧍";
|
||
var tritime = "⨻";
|
||
var trpezium = "⏢";
|
||
var Tscr = "𝒯";
|
||
var tscr = "𝓉";
|
||
var TScy = "Ц";
|
||
var tscy = "ц";
|
||
var TSHcy = "Ћ";
|
||
var tshcy = "ћ";
|
||
var Tstrok = "Ŧ";
|
||
var tstrok = "ŧ";
|
||
var twixt = "≬";
|
||
var twoheadleftarrow = "↞";
|
||
var twoheadrightarrow = "↠";
|
||
var Uacute = "Ú";
|
||
var uacute = "ú";
|
||
var uarr = "↑";
|
||
var Uarr = "↟";
|
||
var uArr = "⇑";
|
||
var Uarrocir = "⥉";
|
||
var Ubrcy = "Ў";
|
||
var ubrcy = "ў";
|
||
var Ubreve = "Ŭ";
|
||
var ubreve = "ŭ";
|
||
var Ucirc = "Û";
|
||
var ucirc = "û";
|
||
var Ucy = "У";
|
||
var ucy = "у";
|
||
var udarr = "⇅";
|
||
var Udblac = "Ű";
|
||
var udblac = "ű";
|
||
var udhar = "⥮";
|
||
var ufisht = "⥾";
|
||
var Ufr = "𝔘";
|
||
var ufr = "𝔲";
|
||
var Ugrave = "Ù";
|
||
var ugrave = "ù";
|
||
var uHar = "⥣";
|
||
var uharl = "↿";
|
||
var uharr = "↾";
|
||
var uhblk = "▀";
|
||
var ulcorn = "⌜";
|
||
var ulcorner = "⌜";
|
||
var ulcrop = "⌏";
|
||
var ultri = "◸";
|
||
var Umacr = "Ū";
|
||
var umacr = "ū";
|
||
var uml = "¨";
|
||
var UnderBar = "_";
|
||
var UnderBrace = "⏟";
|
||
var UnderBracket = "⎵";
|
||
var UnderParenthesis = "⏝";
|
||
var Union = "⋃";
|
||
var UnionPlus = "⊎";
|
||
var Uogon = "Ų";
|
||
var uogon = "ų";
|
||
var Uopf = "𝕌";
|
||
var uopf = "𝕦";
|
||
var UpArrowBar = "⤒";
|
||
var uparrow = "↑";
|
||
var UpArrow = "↑";
|
||
var Uparrow = "⇑";
|
||
var UpArrowDownArrow = "⇅";
|
||
var updownarrow = "↕";
|
||
var UpDownArrow = "↕";
|
||
var Updownarrow = "⇕";
|
||
var UpEquilibrium = "⥮";
|
||
var upharpoonleft = "↿";
|
||
var upharpoonright = "↾";
|
||
var uplus = "⊎";
|
||
var UpperLeftArrow = "↖";
|
||
var UpperRightArrow = "↗";
|
||
var upsi = "υ";
|
||
var Upsi = "ϒ";
|
||
var upsih = "ϒ";
|
||
var Upsilon = "Υ";
|
||
var upsilon = "υ";
|
||
var UpTeeArrow = "↥";
|
||
var UpTee = "⊥";
|
||
var upuparrows = "⇈";
|
||
var urcorn = "⌝";
|
||
var urcorner = "⌝";
|
||
var urcrop = "⌎";
|
||
var Uring = "Ů";
|
||
var uring = "ů";
|
||
var urtri = "◹";
|
||
var Uscr = "𝒰";
|
||
var uscr = "𝓊";
|
||
var utdot = "⋰";
|
||
var Utilde = "Ũ";
|
||
var utilde = "ũ";
|
||
var utri = "▵";
|
||
var utrif = "▴";
|
||
var uuarr = "⇈";
|
||
var Uuml = "Ü";
|
||
var uuml = "ü";
|
||
var uwangle = "⦧";
|
||
var vangrt = "⦜";
|
||
var varepsilon = "ϵ";
|
||
var varkappa = "ϰ";
|
||
var varnothing = "∅";
|
||
var varphi = "ϕ";
|
||
var varpi = "ϖ";
|
||
var varpropto = "∝";
|
||
var varr = "↕";
|
||
var vArr = "⇕";
|
||
var varrho = "ϱ";
|
||
var varsigma = "ς";
|
||
var varsubsetneq = "⊊︀";
|
||
var varsubsetneqq = "⫋︀";
|
||
var varsupsetneq = "⊋︀";
|
||
var varsupsetneqq = "⫌︀";
|
||
var vartheta = "ϑ";
|
||
var vartriangleleft = "⊲";
|
||
var vartriangleright = "⊳";
|
||
var vBar = "⫨";
|
||
var Vbar = "⫫";
|
||
var vBarv = "⫩";
|
||
var Vcy = "В";
|
||
var vcy = "в";
|
||
var vdash = "⊢";
|
||
var vDash = "⊨";
|
||
var Vdash = "⊩";
|
||
var VDash = "⊫";
|
||
var Vdashl = "⫦";
|
||
var veebar = "⊻";
|
||
var vee = "∨";
|
||
var Vee = "⋁";
|
||
var veeeq = "≚";
|
||
var vellip = "⋮";
|
||
var verbar = "|";
|
||
var Verbar = "‖";
|
||
var vert = "|";
|
||
var Vert = "‖";
|
||
var VerticalBar = "∣";
|
||
var VerticalLine = "|";
|
||
var VerticalSeparator = "❘";
|
||
var VerticalTilde = "≀";
|
||
var VeryThinSpace = " ";
|
||
var Vfr = "𝔙";
|
||
var vfr = "𝔳";
|
||
var vltri = "⊲";
|
||
var vnsub = "⊂⃒";
|
||
var vnsup = "⊃⃒";
|
||
var Vopf = "𝕍";
|
||
var vopf = "𝕧";
|
||
var vprop = "∝";
|
||
var vrtri = "⊳";
|
||
var Vscr = "𝒱";
|
||
var vscr = "𝓋";
|
||
var vsubnE = "⫋︀";
|
||
var vsubne = "⊊︀";
|
||
var vsupnE = "⫌︀";
|
||
var vsupne = "⊋︀";
|
||
var Vvdash = "⊪";
|
||
var vzigzag = "⦚";
|
||
var Wcirc = "Ŵ";
|
||
var wcirc = "ŵ";
|
||
var wedbar = "⩟";
|
||
var wedge = "∧";
|
||
var Wedge = "⋀";
|
||
var wedgeq = "≙";
|
||
var weierp = "℘";
|
||
var Wfr = "𝔚";
|
||
var wfr = "𝔴";
|
||
var Wopf = "𝕎";
|
||
var wopf = "𝕨";
|
||
var wp = "℘";
|
||
var wr = "≀";
|
||
var wreath = "≀";
|
||
var Wscr = "𝒲";
|
||
var wscr = "𝓌";
|
||
var xcap = "⋂";
|
||
var xcirc = "◯";
|
||
var xcup = "⋃";
|
||
var xdtri = "▽";
|
||
var Xfr = "𝔛";
|
||
var xfr = "𝔵";
|
||
var xharr = "⟷";
|
||
var xhArr = "⟺";
|
||
var Xi = "Ξ";
|
||
var xi = "ξ";
|
||
var xlarr = "⟵";
|
||
var xlArr = "⟸";
|
||
var xmap = "⟼";
|
||
var xnis = "⋻";
|
||
var xodot = "⨀";
|
||
var Xopf = "𝕏";
|
||
var xopf = "𝕩";
|
||
var xoplus = "⨁";
|
||
var xotime = "⨂";
|
||
var xrarr = "⟶";
|
||
var xrArr = "⟹";
|
||
var Xscr = "𝒳";
|
||
var xscr = "𝓍";
|
||
var xsqcup = "⨆";
|
||
var xuplus = "⨄";
|
||
var xutri = "△";
|
||
var xvee = "⋁";
|
||
var xwedge = "⋀";
|
||
var Yacute = "Ý";
|
||
var yacute = "ý";
|
||
var YAcy = "Я";
|
||
var yacy = "я";
|
||
var Ycirc = "Ŷ";
|
||
var ycirc = "ŷ";
|
||
var Ycy = "Ы";
|
||
var ycy = "ы";
|
||
var yen = "¥";
|
||
var Yfr = "𝔜";
|
||
var yfr = "𝔶";
|
||
var YIcy = "Ї";
|
||
var yicy = "ї";
|
||
var Yopf = "𝕐";
|
||
var yopf = "𝕪";
|
||
var Yscr = "𝒴";
|
||
var yscr = "𝓎";
|
||
var YUcy = "Ю";
|
||
var yucy = "ю";
|
||
var yuml = "ÿ";
|
||
var Yuml = "Ÿ";
|
||
var Zacute = "Ź";
|
||
var zacute = "ź";
|
||
var Zcaron = "Ž";
|
||
var zcaron = "ž";
|
||
var Zcy = "З";
|
||
var zcy = "з";
|
||
var Zdot = "Ż";
|
||
var zdot = "ż";
|
||
var zeetrf = "ℨ";
|
||
var ZeroWidthSpace = "";
|
||
var Zeta = "Ζ";
|
||
var zeta = "ζ";
|
||
var zfr = "𝔷";
|
||
var Zfr = "ℨ";
|
||
var ZHcy = "Ж";
|
||
var zhcy = "ж";
|
||
var zigrarr = "⇝";
|
||
var zopf = "𝕫";
|
||
var Zopf = "ℤ";
|
||
var Zscr = "𝒵";
|
||
var zscr = "𝓏";
|
||
var zwj = "";
|
||
var zwnj = "";
|
||
var require$$0 = {
|
||
Aacute: Aacute,
|
||
aacute: aacute,
|
||
Abreve: Abreve,
|
||
abreve: abreve,
|
||
ac: ac,
|
||
acd: acd,
|
||
acE: acE,
|
||
Acirc: Acirc,
|
||
acirc: acirc,
|
||
acute: acute,
|
||
Acy: Acy,
|
||
acy: acy,
|
||
AElig: AElig,
|
||
aelig: aelig,
|
||
af: af,
|
||
Afr: Afr,
|
||
afr: afr,
|
||
Agrave: Agrave,
|
||
agrave: agrave,
|
||
alefsym: alefsym,
|
||
aleph: aleph,
|
||
Alpha: Alpha,
|
||
alpha: alpha,
|
||
Amacr: Amacr,
|
||
amacr: amacr,
|
||
amalg: amalg,
|
||
amp: amp,
|
||
AMP: AMP,
|
||
andand: andand,
|
||
And: And,
|
||
and: and,
|
||
andd: andd,
|
||
andslope: andslope,
|
||
andv: andv,
|
||
ang: ang,
|
||
ange: ange,
|
||
angle: angle,
|
||
angmsdaa: angmsdaa,
|
||
angmsdab: angmsdab,
|
||
angmsdac: angmsdac,
|
||
angmsdad: angmsdad,
|
||
angmsdae: angmsdae,
|
||
angmsdaf: angmsdaf,
|
||
angmsdag: angmsdag,
|
||
angmsdah: angmsdah,
|
||
angmsd: angmsd,
|
||
angrt: angrt,
|
||
angrtvb: angrtvb,
|
||
angrtvbd: angrtvbd,
|
||
angsph: angsph,
|
||
angst: angst,
|
||
angzarr: angzarr,
|
||
Aogon: Aogon,
|
||
aogon: aogon,
|
||
Aopf: Aopf,
|
||
aopf: aopf,
|
||
apacir: apacir,
|
||
ap: ap,
|
||
apE: apE,
|
||
ape: ape,
|
||
apid: apid,
|
||
apos: apos,
|
||
ApplyFunction: ApplyFunction,
|
||
approx: approx,
|
||
approxeq: approxeq,
|
||
Aring: Aring,
|
||
aring: aring,
|
||
Ascr: Ascr,
|
||
ascr: ascr,
|
||
Assign: Assign,
|
||
ast: ast,
|
||
asymp: asymp,
|
||
asympeq: asympeq,
|
||
Atilde: Atilde,
|
||
atilde: atilde,
|
||
Auml: Auml,
|
||
auml: auml,
|
||
awconint: awconint,
|
||
awint: awint,
|
||
backcong: backcong,
|
||
backepsilon: backepsilon,
|
||
backprime: backprime,
|
||
backsim: backsim,
|
||
backsimeq: backsimeq,
|
||
Backslash: Backslash,
|
||
Barv: Barv,
|
||
barvee: barvee,
|
||
barwed: barwed,
|
||
Barwed: Barwed,
|
||
barwedge: barwedge,
|
||
bbrk: bbrk,
|
||
bbrktbrk: bbrktbrk,
|
||
bcong: bcong,
|
||
Bcy: Bcy,
|
||
bcy: bcy,
|
||
bdquo: bdquo,
|
||
becaus: becaus,
|
||
because: because,
|
||
Because: Because,
|
||
bemptyv: bemptyv,
|
||
bepsi: bepsi,
|
||
bernou: bernou,
|
||
Bernoullis: Bernoullis,
|
||
Beta: Beta,
|
||
beta: beta,
|
||
beth: beth,
|
||
between: between,
|
||
Bfr: Bfr,
|
||
bfr: bfr,
|
||
bigcap: bigcap,
|
||
bigcirc: bigcirc,
|
||
bigcup: bigcup,
|
||
bigodot: bigodot,
|
||
bigoplus: bigoplus,
|
||
bigotimes: bigotimes,
|
||
bigsqcup: bigsqcup,
|
||
bigstar: bigstar,
|
||
bigtriangledown: bigtriangledown,
|
||
bigtriangleup: bigtriangleup,
|
||
biguplus: biguplus,
|
||
bigvee: bigvee,
|
||
bigwedge: bigwedge,
|
||
bkarow: bkarow,
|
||
blacklozenge: blacklozenge,
|
||
blacksquare: blacksquare,
|
||
blacktriangle: blacktriangle,
|
||
blacktriangledown: blacktriangledown,
|
||
blacktriangleleft: blacktriangleleft,
|
||
blacktriangleright: blacktriangleright,
|
||
blank: blank,
|
||
blk12: blk12,
|
||
blk14: blk14,
|
||
blk34: blk34,
|
||
block: block$1,
|
||
bne: bne,
|
||
bnequiv: bnequiv,
|
||
bNot: bNot,
|
||
bnot: bnot,
|
||
Bopf: Bopf,
|
||
bopf: bopf,
|
||
bot: bot,
|
||
bottom: bottom,
|
||
bowtie: bowtie,
|
||
boxbox: boxbox,
|
||
boxdl: boxdl,
|
||
boxdL: boxdL,
|
||
boxDl: boxDl,
|
||
boxDL: boxDL,
|
||
boxdr: boxdr,
|
||
boxdR: boxdR,
|
||
boxDr: boxDr,
|
||
boxDR: boxDR,
|
||
boxh: boxh,
|
||
boxH: boxH,
|
||
boxhd: boxhd,
|
||
boxHd: boxHd,
|
||
boxhD: boxhD,
|
||
boxHD: boxHD,
|
||
boxhu: boxhu,
|
||
boxHu: boxHu,
|
||
boxhU: boxhU,
|
||
boxHU: boxHU,
|
||
boxminus: boxminus,
|
||
boxplus: boxplus,
|
||
boxtimes: boxtimes,
|
||
boxul: boxul,
|
||
boxuL: boxuL,
|
||
boxUl: boxUl,
|
||
boxUL: boxUL,
|
||
boxur: boxur,
|
||
boxuR: boxuR,
|
||
boxUr: boxUr,
|
||
boxUR: boxUR,
|
||
boxv: boxv,
|
||
boxV: boxV,
|
||
boxvh: boxvh,
|
||
boxvH: boxvH,
|
||
boxVh: boxVh,
|
||
boxVH: boxVH,
|
||
boxvl: boxvl,
|
||
boxvL: boxvL,
|
||
boxVl: boxVl,
|
||
boxVL: boxVL,
|
||
boxvr: boxvr,
|
||
boxvR: boxvR,
|
||
boxVr: boxVr,
|
||
boxVR: boxVR,
|
||
bprime: bprime,
|
||
breve: breve,
|
||
Breve: Breve,
|
||
brvbar: brvbar,
|
||
bscr: bscr,
|
||
Bscr: Bscr,
|
||
bsemi: bsemi,
|
||
bsim: bsim,
|
||
bsime: bsime,
|
||
bsolb: bsolb,
|
||
bsol: bsol,
|
||
bsolhsub: bsolhsub,
|
||
bull: bull,
|
||
bullet: bullet,
|
||
bump: bump,
|
||
bumpE: bumpE,
|
||
bumpe: bumpe,
|
||
Bumpeq: Bumpeq,
|
||
bumpeq: bumpeq,
|
||
Cacute: Cacute,
|
||
cacute: cacute,
|
||
capand: capand,
|
||
capbrcup: capbrcup,
|
||
capcap: capcap,
|
||
cap: cap,
|
||
Cap: Cap,
|
||
capcup: capcup,
|
||
capdot: capdot,
|
||
CapitalDifferentialD: CapitalDifferentialD,
|
||
caps: caps,
|
||
caret: caret,
|
||
caron: caron,
|
||
Cayleys: Cayleys,
|
||
ccaps: ccaps,
|
||
Ccaron: Ccaron,
|
||
ccaron: ccaron,
|
||
Ccedil: Ccedil,
|
||
ccedil: ccedil,
|
||
Ccirc: Ccirc,
|
||
ccirc: ccirc,
|
||
Cconint: Cconint,
|
||
ccups: ccups,
|
||
ccupssm: ccupssm,
|
||
Cdot: Cdot,
|
||
cdot: cdot,
|
||
cedil: cedil,
|
||
Cedilla: Cedilla,
|
||
cemptyv: cemptyv,
|
||
cent: cent,
|
||
centerdot: centerdot,
|
||
CenterDot: CenterDot,
|
||
cfr: cfr,
|
||
Cfr: Cfr,
|
||
CHcy: CHcy,
|
||
chcy: chcy,
|
||
check: check,
|
||
checkmark: checkmark,
|
||
Chi: Chi,
|
||
chi: chi,
|
||
circ: circ,
|
||
circeq: circeq,
|
||
circlearrowleft: circlearrowleft,
|
||
circlearrowright: circlearrowright,
|
||
circledast: circledast,
|
||
circledcirc: circledcirc,
|
||
circleddash: circleddash,
|
||
CircleDot: CircleDot,
|
||
circledR: circledR,
|
||
circledS: circledS,
|
||
CircleMinus: CircleMinus,
|
||
CirclePlus: CirclePlus,
|
||
CircleTimes: CircleTimes,
|
||
cir: cir,
|
||
cirE: cirE,
|
||
cire: cire,
|
||
cirfnint: cirfnint,
|
||
cirmid: cirmid,
|
||
cirscir: cirscir,
|
||
ClockwiseContourIntegral: ClockwiseContourIntegral,
|
||
CloseCurlyDoubleQuote: CloseCurlyDoubleQuote,
|
||
CloseCurlyQuote: CloseCurlyQuote,
|
||
clubs: clubs,
|
||
clubsuit: clubsuit,
|
||
colon: colon,
|
||
Colon: Colon,
|
||
Colone: Colone,
|
||
colone: colone,
|
||
coloneq: coloneq,
|
||
comma: comma,
|
||
commat: commat,
|
||
comp: comp,
|
||
compfn: compfn,
|
||
complement: complement,
|
||
complexes: complexes,
|
||
cong: cong,
|
||
congdot: congdot,
|
||
Congruent: Congruent,
|
||
conint: conint,
|
||
Conint: Conint,
|
||
ContourIntegral: ContourIntegral,
|
||
copf: copf,
|
||
Copf: Copf,
|
||
coprod: coprod,
|
||
Coproduct: Coproduct,
|
||
copy: copy,
|
||
COPY: COPY,
|
||
copysr: copysr,
|
||
CounterClockwiseContourIntegral: CounterClockwiseContourIntegral,
|
||
crarr: crarr,
|
||
cross: cross,
|
||
Cross: Cross,
|
||
Cscr: Cscr,
|
||
cscr: cscr,
|
||
csub: csub,
|
||
csube: csube,
|
||
csup: csup,
|
||
csupe: csupe,
|
||
ctdot: ctdot,
|
||
cudarrl: cudarrl,
|
||
cudarrr: cudarrr,
|
||
cuepr: cuepr,
|
||
cuesc: cuesc,
|
||
cularr: cularr,
|
||
cularrp: cularrp,
|
||
cupbrcap: cupbrcap,
|
||
cupcap: cupcap,
|
||
CupCap: CupCap,
|
||
cup: cup,
|
||
Cup: Cup,
|
||
cupcup: cupcup,
|
||
cupdot: cupdot,
|
||
cupor: cupor,
|
||
cups: cups,
|
||
curarr: curarr,
|
||
curarrm: curarrm,
|
||
curlyeqprec: curlyeqprec,
|
||
curlyeqsucc: curlyeqsucc,
|
||
curlyvee: curlyvee,
|
||
curlywedge: curlywedge,
|
||
curren: curren,
|
||
curvearrowleft: curvearrowleft,
|
||
curvearrowright: curvearrowright,
|
||
cuvee: cuvee,
|
||
cuwed: cuwed,
|
||
cwconint: cwconint,
|
||
cwint: cwint,
|
||
cylcty: cylcty,
|
||
dagger: dagger,
|
||
Dagger: Dagger,
|
||
daleth: daleth,
|
||
darr: darr,
|
||
Darr: Darr,
|
||
dArr: dArr,
|
||
dash: dash,
|
||
Dashv: Dashv,
|
||
dashv: dashv,
|
||
dbkarow: dbkarow,
|
||
dblac: dblac,
|
||
Dcaron: Dcaron,
|
||
dcaron: dcaron,
|
||
Dcy: Dcy,
|
||
dcy: dcy,
|
||
ddagger: ddagger,
|
||
ddarr: ddarr,
|
||
DD: DD,
|
||
dd: dd,
|
||
DDotrahd: DDotrahd,
|
||
ddotseq: ddotseq,
|
||
deg: deg,
|
||
Del: Del,
|
||
Delta: Delta,
|
||
delta: delta,
|
||
demptyv: demptyv,
|
||
dfisht: dfisht,
|
||
Dfr: Dfr,
|
||
dfr: dfr,
|
||
dHar: dHar,
|
||
dharl: dharl,
|
||
dharr: dharr,
|
||
DiacriticalAcute: DiacriticalAcute,
|
||
DiacriticalDot: DiacriticalDot,
|
||
DiacriticalDoubleAcute: DiacriticalDoubleAcute,
|
||
DiacriticalGrave: DiacriticalGrave,
|
||
DiacriticalTilde: DiacriticalTilde,
|
||
diam: diam,
|
||
diamond: diamond,
|
||
Diamond: Diamond,
|
||
diamondsuit: diamondsuit,
|
||
diams: diams,
|
||
die: die,
|
||
DifferentialD: DifferentialD,
|
||
digamma: digamma,
|
||
disin: disin,
|
||
div: div,
|
||
divide: divide,
|
||
divideontimes: divideontimes,
|
||
divonx: divonx,
|
||
DJcy: DJcy,
|
||
djcy: djcy,
|
||
dlcorn: dlcorn,
|
||
dlcrop: dlcrop,
|
||
dollar: dollar,
|
||
Dopf: Dopf,
|
||
dopf: dopf,
|
||
Dot: Dot,
|
||
dot: dot,
|
||
DotDot: DotDot,
|
||
doteq: doteq,
|
||
doteqdot: doteqdot,
|
||
DotEqual: DotEqual,
|
||
dotminus: dotminus,
|
||
dotplus: dotplus,
|
||
dotsquare: dotsquare,
|
||
doublebarwedge: doublebarwedge,
|
||
DoubleContourIntegral: DoubleContourIntegral,
|
||
DoubleDot: DoubleDot,
|
||
DoubleDownArrow: DoubleDownArrow,
|
||
DoubleLeftArrow: DoubleLeftArrow,
|
||
DoubleLeftRightArrow: DoubleLeftRightArrow,
|
||
DoubleLeftTee: DoubleLeftTee,
|
||
DoubleLongLeftArrow: DoubleLongLeftArrow,
|
||
DoubleLongLeftRightArrow: DoubleLongLeftRightArrow,
|
||
DoubleLongRightArrow: DoubleLongRightArrow,
|
||
DoubleRightArrow: DoubleRightArrow,
|
||
DoubleRightTee: DoubleRightTee,
|
||
DoubleUpArrow: DoubleUpArrow,
|
||
DoubleUpDownArrow: DoubleUpDownArrow,
|
||
DoubleVerticalBar: DoubleVerticalBar,
|
||
DownArrowBar: DownArrowBar,
|
||
downarrow: downarrow,
|
||
DownArrow: DownArrow,
|
||
Downarrow: Downarrow,
|
||
DownArrowUpArrow: DownArrowUpArrow,
|
||
DownBreve: DownBreve,
|
||
downdownarrows: downdownarrows,
|
||
downharpoonleft: downharpoonleft,
|
||
downharpoonright: downharpoonright,
|
||
DownLeftRightVector: DownLeftRightVector,
|
||
DownLeftTeeVector: DownLeftTeeVector,
|
||
DownLeftVectorBar: DownLeftVectorBar,
|
||
DownLeftVector: DownLeftVector,
|
||
DownRightTeeVector: DownRightTeeVector,
|
||
DownRightVectorBar: DownRightVectorBar,
|
||
DownRightVector: DownRightVector,
|
||
DownTeeArrow: DownTeeArrow,
|
||
DownTee: DownTee,
|
||
drbkarow: drbkarow,
|
||
drcorn: drcorn,
|
||
drcrop: drcrop,
|
||
Dscr: Dscr,
|
||
dscr: dscr,
|
||
DScy: DScy,
|
||
dscy: dscy,
|
||
dsol: dsol,
|
||
Dstrok: Dstrok,
|
||
dstrok: dstrok,
|
||
dtdot: dtdot,
|
||
dtri: dtri,
|
||
dtrif: dtrif,
|
||
duarr: duarr,
|
||
duhar: duhar,
|
||
dwangle: dwangle,
|
||
DZcy: DZcy,
|
||
dzcy: dzcy,
|
||
dzigrarr: dzigrarr,
|
||
Eacute: Eacute,
|
||
eacute: eacute,
|
||
easter: easter,
|
||
Ecaron: Ecaron,
|
||
ecaron: ecaron,
|
||
Ecirc: Ecirc,
|
||
ecirc: ecirc,
|
||
ecir: ecir,
|
||
ecolon: ecolon,
|
||
Ecy: Ecy,
|
||
ecy: ecy,
|
||
eDDot: eDDot,
|
||
Edot: Edot,
|
||
edot: edot,
|
||
eDot: eDot,
|
||
ee: ee,
|
||
efDot: efDot,
|
||
Efr: Efr,
|
||
efr: efr,
|
||
eg: eg,
|
||
Egrave: Egrave,
|
||
egrave: egrave,
|
||
egs: egs,
|
||
egsdot: egsdot,
|
||
el: el,
|
||
Element: Element,
|
||
elinters: elinters,
|
||
ell: ell,
|
||
els: els,
|
||
elsdot: elsdot,
|
||
Emacr: Emacr,
|
||
emacr: emacr,
|
||
empty: empty,
|
||
emptyset: emptyset,
|
||
EmptySmallSquare: EmptySmallSquare,
|
||
emptyv: emptyv,
|
||
EmptyVerySmallSquare: EmptyVerySmallSquare,
|
||
emsp13: emsp13,
|
||
emsp14: emsp14,
|
||
emsp: emsp,
|
||
ENG: ENG,
|
||
eng: eng,
|
||
ensp: ensp,
|
||
Eogon: Eogon,
|
||
eogon: eogon,
|
||
Eopf: Eopf,
|
||
eopf: eopf,
|
||
epar: epar,
|
||
eparsl: eparsl,
|
||
eplus: eplus,
|
||
epsi: epsi,
|
||
Epsilon: Epsilon,
|
||
epsilon: epsilon,
|
||
epsiv: epsiv,
|
||
eqcirc: eqcirc,
|
||
eqcolon: eqcolon,
|
||
eqsim: eqsim,
|
||
eqslantgtr: eqslantgtr,
|
||
eqslantless: eqslantless,
|
||
Equal: Equal,
|
||
equals: equals,
|
||
EqualTilde: EqualTilde,
|
||
equest: equest,
|
||
Equilibrium: Equilibrium,
|
||
equiv: equiv,
|
||
equivDD: equivDD,
|
||
eqvparsl: eqvparsl,
|
||
erarr: erarr,
|
||
erDot: erDot,
|
||
escr: escr,
|
||
Escr: Escr,
|
||
esdot: esdot,
|
||
Esim: Esim,
|
||
esim: esim,
|
||
Eta: Eta,
|
||
eta: eta,
|
||
ETH: ETH,
|
||
eth: eth,
|
||
Euml: Euml,
|
||
euml: euml,
|
||
euro: euro,
|
||
excl: excl,
|
||
exist: exist,
|
||
Exists: Exists,
|
||
expectation: expectation,
|
||
exponentiale: exponentiale,
|
||
ExponentialE: ExponentialE,
|
||
fallingdotseq: fallingdotseq,
|
||
Fcy: Fcy,
|
||
fcy: fcy,
|
||
female: female,
|
||
ffilig: ffilig,
|
||
fflig: fflig,
|
||
ffllig: ffllig,
|
||
Ffr: Ffr,
|
||
ffr: ffr,
|
||
filig: filig,
|
||
FilledSmallSquare: FilledSmallSquare,
|
||
FilledVerySmallSquare: FilledVerySmallSquare,
|
||
fjlig: fjlig,
|
||
flat: flat,
|
||
fllig: fllig,
|
||
fltns: fltns,
|
||
fnof: fnof,
|
||
Fopf: Fopf,
|
||
fopf: fopf,
|
||
forall: forall,
|
||
ForAll: ForAll,
|
||
fork: fork,
|
||
forkv: forkv,
|
||
Fouriertrf: Fouriertrf,
|
||
fpartint: fpartint,
|
||
frac12: frac12,
|
||
frac13: frac13,
|
||
frac14: frac14,
|
||
frac15: frac15,
|
||
frac16: frac16,
|
||
frac18: frac18,
|
||
frac23: frac23,
|
||
frac25: frac25,
|
||
frac34: frac34,
|
||
frac35: frac35,
|
||
frac38: frac38,
|
||
frac45: frac45,
|
||
frac56: frac56,
|
||
frac58: frac58,
|
||
frac78: frac78,
|
||
frasl: frasl,
|
||
frown: frown,
|
||
fscr: fscr,
|
||
Fscr: Fscr,
|
||
gacute: gacute,
|
||
Gamma: Gamma,
|
||
gamma: gamma,
|
||
Gammad: Gammad,
|
||
gammad: gammad,
|
||
gap: gap,
|
||
Gbreve: Gbreve,
|
||
gbreve: gbreve,
|
||
Gcedil: Gcedil,
|
||
Gcirc: Gcirc,
|
||
gcirc: gcirc,
|
||
Gcy: Gcy,
|
||
gcy: gcy,
|
||
Gdot: Gdot,
|
||
gdot: gdot,
|
||
ge: ge,
|
||
gE: gE,
|
||
gEl: gEl,
|
||
gel: gel,
|
||
geq: geq,
|
||
geqq: geqq,
|
||
geqslant: geqslant,
|
||
gescc: gescc,
|
||
ges: ges,
|
||
gesdot: gesdot,
|
||
gesdoto: gesdoto,
|
||
gesdotol: gesdotol,
|
||
gesl: gesl,
|
||
gesles: gesles,
|
||
Gfr: Gfr,
|
||
gfr: gfr,
|
||
gg: gg,
|
||
Gg: Gg,
|
||
ggg: ggg,
|
||
gimel: gimel,
|
||
GJcy: GJcy,
|
||
gjcy: gjcy,
|
||
gla: gla,
|
||
gl: gl,
|
||
glE: glE,
|
||
glj: glj,
|
||
gnap: gnap,
|
||
gnapprox: gnapprox,
|
||
gne: gne,
|
||
gnE: gnE,
|
||
gneq: gneq,
|
||
gneqq: gneqq,
|
||
gnsim: gnsim,
|
||
Gopf: Gopf,
|
||
gopf: gopf,
|
||
grave: grave,
|
||
GreaterEqual: GreaterEqual,
|
||
GreaterEqualLess: GreaterEqualLess,
|
||
GreaterFullEqual: GreaterFullEqual,
|
||
GreaterGreater: GreaterGreater,
|
||
GreaterLess: GreaterLess,
|
||
GreaterSlantEqual: GreaterSlantEqual,
|
||
GreaterTilde: GreaterTilde,
|
||
Gscr: Gscr,
|
||
gscr: gscr,
|
||
gsim: gsim,
|
||
gsime: gsime,
|
||
gsiml: gsiml,
|
||
gtcc: gtcc,
|
||
gtcir: gtcir,
|
||
gt: gt,
|
||
GT: GT,
|
||
Gt: Gt,
|
||
gtdot: gtdot,
|
||
gtlPar: gtlPar,
|
||
gtquest: gtquest,
|
||
gtrapprox: gtrapprox,
|
||
gtrarr: gtrarr,
|
||
gtrdot: gtrdot,
|
||
gtreqless: gtreqless,
|
||
gtreqqless: gtreqqless,
|
||
gtrless: gtrless,
|
||
gtrsim: gtrsim,
|
||
gvertneqq: gvertneqq,
|
||
gvnE: gvnE,
|
||
Hacek: Hacek,
|
||
hairsp: hairsp,
|
||
half: half,
|
||
hamilt: hamilt,
|
||
HARDcy: HARDcy,
|
||
hardcy: hardcy,
|
||
harrcir: harrcir,
|
||
harr: harr,
|
||
hArr: hArr,
|
||
harrw: harrw,
|
||
Hat: Hat,
|
||
hbar: hbar,
|
||
Hcirc: Hcirc,
|
||
hcirc: hcirc,
|
||
hearts: hearts,
|
||
heartsuit: heartsuit,
|
||
hellip: hellip,
|
||
hercon: hercon,
|
||
hfr: hfr,
|
||
Hfr: Hfr,
|
||
HilbertSpace: HilbertSpace,
|
||
hksearow: hksearow,
|
||
hkswarow: hkswarow,
|
||
hoarr: hoarr,
|
||
homtht: homtht,
|
||
hookleftarrow: hookleftarrow,
|
||
hookrightarrow: hookrightarrow,
|
||
hopf: hopf,
|
||
Hopf: Hopf,
|
||
horbar: horbar,
|
||
HorizontalLine: HorizontalLine,
|
||
hscr: hscr,
|
||
Hscr: Hscr,
|
||
hslash: hslash,
|
||
Hstrok: Hstrok,
|
||
hstrok: hstrok,
|
||
HumpDownHump: HumpDownHump,
|
||
HumpEqual: HumpEqual,
|
||
hybull: hybull,
|
||
hyphen: hyphen,
|
||
Iacute: Iacute,
|
||
iacute: iacute,
|
||
ic: ic,
|
||
Icirc: Icirc,
|
||
icirc: icirc,
|
||
Icy: Icy,
|
||
icy: icy,
|
||
Idot: Idot,
|
||
IEcy: IEcy,
|
||
iecy: iecy,
|
||
iexcl: iexcl,
|
||
iff: iff,
|
||
ifr: ifr,
|
||
Ifr: Ifr,
|
||
Igrave: Igrave,
|
||
igrave: igrave,
|
||
ii: ii,
|
||
iiiint: iiiint,
|
||
iiint: iiint,
|
||
iinfin: iinfin,
|
||
iiota: iiota,
|
||
IJlig: IJlig,
|
||
ijlig: ijlig,
|
||
Imacr: Imacr,
|
||
imacr: imacr,
|
||
image: image$1,
|
||
ImaginaryI: ImaginaryI,
|
||
imagline: imagline,
|
||
imagpart: imagpart,
|
||
imath: imath,
|
||
Im: Im,
|
||
imof: imof,
|
||
imped: imped,
|
||
Implies: Implies,
|
||
incare: incare,
|
||
"in": "∈",
|
||
infin: infin,
|
||
infintie: infintie,
|
||
inodot: inodot,
|
||
intcal: intcal,
|
||
int: int,
|
||
Int: Int,
|
||
integers: integers,
|
||
Integral: Integral,
|
||
intercal: intercal,
|
||
Intersection: Intersection,
|
||
intlarhk: intlarhk,
|
||
intprod: intprod,
|
||
InvisibleComma: InvisibleComma,
|
||
InvisibleTimes: InvisibleTimes,
|
||
IOcy: IOcy,
|
||
iocy: iocy,
|
||
Iogon: Iogon,
|
||
iogon: iogon,
|
||
Iopf: Iopf,
|
||
iopf: iopf,
|
||
Iota: Iota,
|
||
iota: iota,
|
||
iprod: iprod,
|
||
iquest: iquest,
|
||
iscr: iscr,
|
||
Iscr: Iscr,
|
||
isin: isin,
|
||
isindot: isindot,
|
||
isinE: isinE,
|
||
isins: isins,
|
||
isinsv: isinsv,
|
||
isinv: isinv,
|
||
it: it,
|
||
Itilde: Itilde,
|
||
itilde: itilde,
|
||
Iukcy: Iukcy,
|
||
iukcy: iukcy,
|
||
Iuml: Iuml,
|
||
iuml: iuml,
|
||
Jcirc: Jcirc,
|
||
jcirc: jcirc,
|
||
Jcy: Jcy,
|
||
jcy: jcy,
|
||
Jfr: Jfr,
|
||
jfr: jfr,
|
||
jmath: jmath,
|
||
Jopf: Jopf,
|
||
jopf: jopf,
|
||
Jscr: Jscr,
|
||
jscr: jscr,
|
||
Jsercy: Jsercy,
|
||
jsercy: jsercy,
|
||
Jukcy: Jukcy,
|
||
jukcy: jukcy,
|
||
Kappa: Kappa,
|
||
kappa: kappa,
|
||
kappav: kappav,
|
||
Kcedil: Kcedil,
|
||
kcedil: kcedil,
|
||
Kcy: Kcy,
|
||
kcy: kcy,
|
||
Kfr: Kfr,
|
||
kfr: kfr,
|
||
kgreen: kgreen,
|
||
KHcy: KHcy,
|
||
khcy: khcy,
|
||
KJcy: KJcy,
|
||
kjcy: kjcy,
|
||
Kopf: Kopf,
|
||
kopf: kopf,
|
||
Kscr: Kscr,
|
||
kscr: kscr,
|
||
lAarr: lAarr,
|
||
Lacute: Lacute,
|
||
lacute: lacute,
|
||
laemptyv: laemptyv,
|
||
lagran: lagran,
|
||
Lambda: Lambda,
|
||
lambda: lambda,
|
||
lang: lang,
|
||
Lang: Lang,
|
||
langd: langd,
|
||
langle: langle,
|
||
lap: lap,
|
||
Laplacetrf: Laplacetrf,
|
||
laquo: laquo,
|
||
larrb: larrb,
|
||
larrbfs: larrbfs,
|
||
larr: larr,
|
||
Larr: Larr,
|
||
lArr: lArr,
|
||
larrfs: larrfs,
|
||
larrhk: larrhk,
|
||
larrlp: larrlp,
|
||
larrpl: larrpl,
|
||
larrsim: larrsim,
|
||
larrtl: larrtl,
|
||
latail: latail,
|
||
lAtail: lAtail,
|
||
lat: lat,
|
||
late: late,
|
||
lates: lates,
|
||
lbarr: lbarr,
|
||
lBarr: lBarr,
|
||
lbbrk: lbbrk,
|
||
lbrace: lbrace,
|
||
lbrack: lbrack,
|
||
lbrke: lbrke,
|
||
lbrksld: lbrksld,
|
||
lbrkslu: lbrkslu,
|
||
Lcaron: Lcaron,
|
||
lcaron: lcaron,
|
||
Lcedil: Lcedil,
|
||
lcedil: lcedil,
|
||
lceil: lceil,
|
||
lcub: lcub,
|
||
Lcy: Lcy,
|
||
lcy: lcy,
|
||
ldca: ldca,
|
||
ldquo: ldquo,
|
||
ldquor: ldquor,
|
||
ldrdhar: ldrdhar,
|
||
ldrushar: ldrushar,
|
||
ldsh: ldsh,
|
||
le: le,
|
||
lE: lE,
|
||
LeftAngleBracket: LeftAngleBracket,
|
||
LeftArrowBar: LeftArrowBar,
|
||
leftarrow: leftarrow,
|
||
LeftArrow: LeftArrow,
|
||
Leftarrow: Leftarrow,
|
||
LeftArrowRightArrow: LeftArrowRightArrow,
|
||
leftarrowtail: leftarrowtail,
|
||
LeftCeiling: LeftCeiling,
|
||
LeftDoubleBracket: LeftDoubleBracket,
|
||
LeftDownTeeVector: LeftDownTeeVector,
|
||
LeftDownVectorBar: LeftDownVectorBar,
|
||
LeftDownVector: LeftDownVector,
|
||
LeftFloor: LeftFloor,
|
||
leftharpoondown: leftharpoondown,
|
||
leftharpoonup: leftharpoonup,
|
||
leftleftarrows: leftleftarrows,
|
||
leftrightarrow: leftrightarrow,
|
||
LeftRightArrow: LeftRightArrow,
|
||
Leftrightarrow: Leftrightarrow,
|
||
leftrightarrows: leftrightarrows,
|
||
leftrightharpoons: leftrightharpoons,
|
||
leftrightsquigarrow: leftrightsquigarrow,
|
||
LeftRightVector: LeftRightVector,
|
||
LeftTeeArrow: LeftTeeArrow,
|
||
LeftTee: LeftTee,
|
||
LeftTeeVector: LeftTeeVector,
|
||
leftthreetimes: leftthreetimes,
|
||
LeftTriangleBar: LeftTriangleBar,
|
||
LeftTriangle: LeftTriangle,
|
||
LeftTriangleEqual: LeftTriangleEqual,
|
||
LeftUpDownVector: LeftUpDownVector,
|
||
LeftUpTeeVector: LeftUpTeeVector,
|
||
LeftUpVectorBar: LeftUpVectorBar,
|
||
LeftUpVector: LeftUpVector,
|
||
LeftVectorBar: LeftVectorBar,
|
||
LeftVector: LeftVector,
|
||
lEg: lEg,
|
||
leg: leg,
|
||
leq: leq,
|
||
leqq: leqq,
|
||
leqslant: leqslant,
|
||
lescc: lescc,
|
||
les: les,
|
||
lesdot: lesdot,
|
||
lesdoto: lesdoto,
|
||
lesdotor: lesdotor,
|
||
lesg: lesg,
|
||
lesges: lesges,
|
||
lessapprox: lessapprox,
|
||
lessdot: lessdot,
|
||
lesseqgtr: lesseqgtr,
|
||
lesseqqgtr: lesseqqgtr,
|
||
LessEqualGreater: LessEqualGreater,
|
||
LessFullEqual: LessFullEqual,
|
||
LessGreater: LessGreater,
|
||
lessgtr: lessgtr,
|
||
LessLess: LessLess,
|
||
lesssim: lesssim,
|
||
LessSlantEqual: LessSlantEqual,
|
||
LessTilde: LessTilde,
|
||
lfisht: lfisht,
|
||
lfloor: lfloor,
|
||
Lfr: Lfr,
|
||
lfr: lfr,
|
||
lg: lg,
|
||
lgE: lgE,
|
||
lHar: lHar,
|
||
lhard: lhard,
|
||
lharu: lharu,
|
||
lharul: lharul,
|
||
lhblk: lhblk,
|
||
LJcy: LJcy,
|
||
ljcy: ljcy,
|
||
llarr: llarr,
|
||
ll: ll,
|
||
Ll: Ll,
|
||
llcorner: llcorner,
|
||
Lleftarrow: Lleftarrow,
|
||
llhard: llhard,
|
||
lltri: lltri,
|
||
Lmidot: Lmidot,
|
||
lmidot: lmidot,
|
||
lmoustache: lmoustache,
|
||
lmoust: lmoust,
|
||
lnap: lnap,
|
||
lnapprox: lnapprox,
|
||
lne: lne,
|
||
lnE: lnE,
|
||
lneq: lneq,
|
||
lneqq: lneqq,
|
||
lnsim: lnsim,
|
||
loang: loang,
|
||
loarr: loarr,
|
||
lobrk: lobrk,
|
||
longleftarrow: longleftarrow,
|
||
LongLeftArrow: LongLeftArrow,
|
||
Longleftarrow: Longleftarrow,
|
||
longleftrightarrow: longleftrightarrow,
|
||
LongLeftRightArrow: LongLeftRightArrow,
|
||
Longleftrightarrow: Longleftrightarrow,
|
||
longmapsto: longmapsto,
|
||
longrightarrow: longrightarrow,
|
||
LongRightArrow: LongRightArrow,
|
||
Longrightarrow: Longrightarrow,
|
||
looparrowleft: looparrowleft,
|
||
looparrowright: looparrowright,
|
||
lopar: lopar,
|
||
Lopf: Lopf,
|
||
lopf: lopf,
|
||
loplus: loplus,
|
||
lotimes: lotimes,
|
||
lowast: lowast,
|
||
lowbar: lowbar,
|
||
LowerLeftArrow: LowerLeftArrow,
|
||
LowerRightArrow: LowerRightArrow,
|
||
loz: loz,
|
||
lozenge: lozenge,
|
||
lozf: lozf,
|
||
lpar: lpar,
|
||
lparlt: lparlt,
|
||
lrarr: lrarr,
|
||
lrcorner: lrcorner,
|
||
lrhar: lrhar,
|
||
lrhard: lrhard,
|
||
lrm: lrm,
|
||
lrtri: lrtri,
|
||
lsaquo: lsaquo,
|
||
lscr: lscr,
|
||
Lscr: Lscr,
|
||
lsh: lsh,
|
||
Lsh: Lsh,
|
||
lsim: lsim,
|
||
lsime: lsime,
|
||
lsimg: lsimg,
|
||
lsqb: lsqb,
|
||
lsquo: lsquo,
|
||
lsquor: lsquor,
|
||
Lstrok: Lstrok,
|
||
lstrok: lstrok,
|
||
ltcc: ltcc,
|
||
ltcir: ltcir,
|
||
lt: lt,
|
||
LT: LT,
|
||
Lt: Lt,
|
||
ltdot: ltdot,
|
||
lthree: lthree,
|
||
ltimes: ltimes,
|
||
ltlarr: ltlarr,
|
||
ltquest: ltquest,
|
||
ltri: ltri,
|
||
ltrie: ltrie,
|
||
ltrif: ltrif,
|
||
ltrPar: ltrPar,
|
||
lurdshar: lurdshar,
|
||
luruhar: luruhar,
|
||
lvertneqq: lvertneqq,
|
||
lvnE: lvnE,
|
||
macr: macr,
|
||
male: male,
|
||
malt: malt,
|
||
maltese: maltese,
|
||
"Map": "⤅",
|
||
map: map$1,
|
||
mapsto: mapsto,
|
||
mapstodown: mapstodown,
|
||
mapstoleft: mapstoleft,
|
||
mapstoup: mapstoup,
|
||
marker: marker,
|
||
mcomma: mcomma,
|
||
Mcy: Mcy,
|
||
mcy: mcy,
|
||
mdash: mdash,
|
||
mDDot: mDDot,
|
||
measuredangle: measuredangle,
|
||
MediumSpace: MediumSpace,
|
||
Mellintrf: Mellintrf,
|
||
Mfr: Mfr,
|
||
mfr: mfr,
|
||
mho: mho,
|
||
micro: micro,
|
||
midast: midast,
|
||
midcir: midcir,
|
||
mid: mid,
|
||
middot: middot,
|
||
minusb: minusb,
|
||
minus: minus,
|
||
minusd: minusd,
|
||
minusdu: minusdu,
|
||
MinusPlus: MinusPlus,
|
||
mlcp: mlcp,
|
||
mldr: mldr,
|
||
mnplus: mnplus,
|
||
models: models,
|
||
Mopf: Mopf,
|
||
mopf: mopf,
|
||
mp: mp,
|
||
mscr: mscr,
|
||
Mscr: Mscr,
|
||
mstpos: mstpos,
|
||
Mu: Mu,
|
||
mu: mu,
|
||
multimap: multimap,
|
||
mumap: mumap,
|
||
nabla: nabla,
|
||
Nacute: Nacute,
|
||
nacute: nacute,
|
||
nang: nang,
|
||
nap: nap,
|
||
napE: napE,
|
||
napid: napid,
|
||
napos: napos,
|
||
napprox: napprox,
|
||
natural: natural,
|
||
naturals: naturals,
|
||
natur: natur,
|
||
nbsp: nbsp,
|
||
nbump: nbump,
|
||
nbumpe: nbumpe,
|
||
ncap: ncap,
|
||
Ncaron: Ncaron,
|
||
ncaron: ncaron,
|
||
Ncedil: Ncedil,
|
||
ncedil: ncedil,
|
||
ncong: ncong,
|
||
ncongdot: ncongdot,
|
||
ncup: ncup,
|
||
Ncy: Ncy,
|
||
ncy: ncy,
|
||
ndash: ndash,
|
||
nearhk: nearhk,
|
||
nearr: nearr,
|
||
neArr: neArr,
|
||
nearrow: nearrow,
|
||
ne: ne,
|
||
nedot: nedot,
|
||
NegativeMediumSpace: NegativeMediumSpace,
|
||
NegativeThickSpace: NegativeThickSpace,
|
||
NegativeThinSpace: NegativeThinSpace,
|
||
NegativeVeryThinSpace: NegativeVeryThinSpace,
|
||
nequiv: nequiv,
|
||
nesear: nesear,
|
||
nesim: nesim,
|
||
NestedGreaterGreater: NestedGreaterGreater,
|
||
NestedLessLess: NestedLessLess,
|
||
NewLine: NewLine,
|
||
nexist: nexist,
|
||
nexists: nexists,
|
||
Nfr: Nfr,
|
||
nfr: nfr,
|
||
ngE: ngE,
|
||
nge: nge,
|
||
ngeq: ngeq,
|
||
ngeqq: ngeqq,
|
||
ngeqslant: ngeqslant,
|
||
nges: nges,
|
||
nGg: nGg,
|
||
ngsim: ngsim,
|
||
nGt: nGt,
|
||
ngt: ngt,
|
||
ngtr: ngtr,
|
||
nGtv: nGtv,
|
||
nharr: nharr,
|
||
nhArr: nhArr,
|
||
nhpar: nhpar,
|
||
ni: ni,
|
||
nis: nis,
|
||
nisd: nisd,
|
||
niv: niv,
|
||
NJcy: NJcy,
|
||
njcy: njcy,
|
||
nlarr: nlarr,
|
||
nlArr: nlArr,
|
||
nldr: nldr,
|
||
nlE: nlE,
|
||
nle: nle,
|
||
nleftarrow: nleftarrow,
|
||
nLeftarrow: nLeftarrow,
|
||
nleftrightarrow: nleftrightarrow,
|
||
nLeftrightarrow: nLeftrightarrow,
|
||
nleq: nleq,
|
||
nleqq: nleqq,
|
||
nleqslant: nleqslant,
|
||
nles: nles,
|
||
nless: nless,
|
||
nLl: nLl,
|
||
nlsim: nlsim,
|
||
nLt: nLt,
|
||
nlt: nlt,
|
||
nltri: nltri,
|
||
nltrie: nltrie,
|
||
nLtv: nLtv,
|
||
nmid: nmid,
|
||
NoBreak: NoBreak,
|
||
NonBreakingSpace: NonBreakingSpace,
|
||
nopf: nopf,
|
||
Nopf: Nopf,
|
||
Not: Not,
|
||
not: not,
|
||
NotCongruent: NotCongruent,
|
||
NotCupCap: NotCupCap,
|
||
NotDoubleVerticalBar: NotDoubleVerticalBar,
|
||
NotElement: NotElement,
|
||
NotEqual: NotEqual,
|
||
NotEqualTilde: NotEqualTilde,
|
||
NotExists: NotExists,
|
||
NotGreater: NotGreater,
|
||
NotGreaterEqual: NotGreaterEqual,
|
||
NotGreaterFullEqual: NotGreaterFullEqual,
|
||
NotGreaterGreater: NotGreaterGreater,
|
||
NotGreaterLess: NotGreaterLess,
|
||
NotGreaterSlantEqual: NotGreaterSlantEqual,
|
||
NotGreaterTilde: NotGreaterTilde,
|
||
NotHumpDownHump: NotHumpDownHump,
|
||
NotHumpEqual: NotHumpEqual,
|
||
notin: notin,
|
||
notindot: notindot,
|
||
notinE: notinE,
|
||
notinva: notinva,
|
||
notinvb: notinvb,
|
||
notinvc: notinvc,
|
||
NotLeftTriangleBar: NotLeftTriangleBar,
|
||
NotLeftTriangle: NotLeftTriangle,
|
||
NotLeftTriangleEqual: NotLeftTriangleEqual,
|
||
NotLess: NotLess,
|
||
NotLessEqual: NotLessEqual,
|
||
NotLessGreater: NotLessGreater,
|
||
NotLessLess: NotLessLess,
|
||
NotLessSlantEqual: NotLessSlantEqual,
|
||
NotLessTilde: NotLessTilde,
|
||
NotNestedGreaterGreater: NotNestedGreaterGreater,
|
||
NotNestedLessLess: NotNestedLessLess,
|
||
notni: notni,
|
||
notniva: notniva,
|
||
notnivb: notnivb,
|
||
notnivc: notnivc,
|
||
NotPrecedes: NotPrecedes,
|
||
NotPrecedesEqual: NotPrecedesEqual,
|
||
NotPrecedesSlantEqual: NotPrecedesSlantEqual,
|
||
NotReverseElement: NotReverseElement,
|
||
NotRightTriangleBar: NotRightTriangleBar,
|
||
NotRightTriangle: NotRightTriangle,
|
||
NotRightTriangleEqual: NotRightTriangleEqual,
|
||
NotSquareSubset: NotSquareSubset,
|
||
NotSquareSubsetEqual: NotSquareSubsetEqual,
|
||
NotSquareSuperset: NotSquareSuperset,
|
||
NotSquareSupersetEqual: NotSquareSupersetEqual,
|
||
NotSubset: NotSubset,
|
||
NotSubsetEqual: NotSubsetEqual,
|
||
NotSucceeds: NotSucceeds,
|
||
NotSucceedsEqual: NotSucceedsEqual,
|
||
NotSucceedsSlantEqual: NotSucceedsSlantEqual,
|
||
NotSucceedsTilde: NotSucceedsTilde,
|
||
NotSuperset: NotSuperset,
|
||
NotSupersetEqual: NotSupersetEqual,
|
||
NotTilde: NotTilde,
|
||
NotTildeEqual: NotTildeEqual,
|
||
NotTildeFullEqual: NotTildeFullEqual,
|
||
NotTildeTilde: NotTildeTilde,
|
||
NotVerticalBar: NotVerticalBar,
|
||
nparallel: nparallel,
|
||
npar: npar,
|
||
nparsl: nparsl,
|
||
npart: npart,
|
||
npolint: npolint,
|
||
npr: npr,
|
||
nprcue: nprcue,
|
||
nprec: nprec,
|
||
npreceq: npreceq,
|
||
npre: npre,
|
||
nrarrc: nrarrc,
|
||
nrarr: nrarr,
|
||
nrArr: nrArr,
|
||
nrarrw: nrarrw,
|
||
nrightarrow: nrightarrow,
|
||
nRightarrow: nRightarrow,
|
||
nrtri: nrtri,
|
||
nrtrie: nrtrie,
|
||
nsc: nsc,
|
||
nsccue: nsccue,
|
||
nsce: nsce,
|
||
Nscr: Nscr,
|
||
nscr: nscr,
|
||
nshortmid: nshortmid,
|
||
nshortparallel: nshortparallel,
|
||
nsim: nsim,
|
||
nsime: nsime,
|
||
nsimeq: nsimeq,
|
||
nsmid: nsmid,
|
||
nspar: nspar,
|
||
nsqsube: nsqsube,
|
||
nsqsupe: nsqsupe,
|
||
nsub: nsub,
|
||
nsubE: nsubE,
|
||
nsube: nsube,
|
||
nsubset: nsubset,
|
||
nsubseteq: nsubseteq,
|
||
nsubseteqq: nsubseteqq,
|
||
nsucc: nsucc,
|
||
nsucceq: nsucceq,
|
||
nsup: nsup,
|
||
nsupE: nsupE,
|
||
nsupe: nsupe,
|
||
nsupset: nsupset,
|
||
nsupseteq: nsupseteq,
|
||
nsupseteqq: nsupseteqq,
|
||
ntgl: ntgl,
|
||
Ntilde: Ntilde,
|
||
ntilde: ntilde,
|
||
ntlg: ntlg,
|
||
ntriangleleft: ntriangleleft,
|
||
ntrianglelefteq: ntrianglelefteq,
|
||
ntriangleright: ntriangleright,
|
||
ntrianglerighteq: ntrianglerighteq,
|
||
Nu: Nu,
|
||
nu: nu,
|
||
num: num,
|
||
numero: numero,
|
||
numsp: numsp,
|
||
nvap: nvap,
|
||
nvdash: nvdash,
|
||
nvDash: nvDash,
|
||
nVdash: nVdash,
|
||
nVDash: nVDash,
|
||
nvge: nvge,
|
||
nvgt: nvgt,
|
||
nvHarr: nvHarr,
|
||
nvinfin: nvinfin,
|
||
nvlArr: nvlArr,
|
||
nvle: nvle,
|
||
nvlt: nvlt,
|
||
nvltrie: nvltrie,
|
||
nvrArr: nvrArr,
|
||
nvrtrie: nvrtrie,
|
||
nvsim: nvsim,
|
||
nwarhk: nwarhk,
|
||
nwarr: nwarr,
|
||
nwArr: nwArr,
|
||
nwarrow: nwarrow,
|
||
nwnear: nwnear,
|
||
Oacute: Oacute,
|
||
oacute: oacute,
|
||
oast: oast,
|
||
Ocirc: Ocirc,
|
||
ocirc: ocirc,
|
||
ocir: ocir,
|
||
Ocy: Ocy,
|
||
ocy: ocy,
|
||
odash: odash,
|
||
Odblac: Odblac,
|
||
odblac: odblac,
|
||
odiv: odiv,
|
||
odot: odot,
|
||
odsold: odsold,
|
||
OElig: OElig,
|
||
oelig: oelig,
|
||
ofcir: ofcir,
|
||
Ofr: Ofr,
|
||
ofr: ofr,
|
||
ogon: ogon,
|
||
Ograve: Ograve,
|
||
ograve: ograve,
|
||
ogt: ogt,
|
||
ohbar: ohbar,
|
||
ohm: ohm,
|
||
oint: oint,
|
||
olarr: olarr,
|
||
olcir: olcir,
|
||
olcross: olcross,
|
||
oline: oline,
|
||
olt: olt,
|
||
Omacr: Omacr,
|
||
omacr: omacr,
|
||
Omega: Omega,
|
||
omega: omega,
|
||
Omicron: Omicron,
|
||
omicron: omicron,
|
||
omid: omid,
|
||
ominus: ominus,
|
||
Oopf: Oopf,
|
||
oopf: oopf,
|
||
opar: opar,
|
||
OpenCurlyDoubleQuote: OpenCurlyDoubleQuote,
|
||
OpenCurlyQuote: OpenCurlyQuote,
|
||
operp: operp,
|
||
oplus: oplus,
|
||
orarr: orarr,
|
||
Or: Or,
|
||
or: or,
|
||
ord: ord,
|
||
order: order,
|
||
orderof: orderof,
|
||
ordf: ordf,
|
||
ordm: ordm,
|
||
origof: origof,
|
||
oror: oror,
|
||
orslope: orslope,
|
||
orv: orv,
|
||
oS: oS,
|
||
Oscr: Oscr,
|
||
oscr: oscr,
|
||
Oslash: Oslash,
|
||
oslash: oslash,
|
||
osol: osol,
|
||
Otilde: Otilde,
|
||
otilde: otilde,
|
||
otimesas: otimesas,
|
||
Otimes: Otimes,
|
||
otimes: otimes,
|
||
Ouml: Ouml,
|
||
ouml: ouml,
|
||
ovbar: ovbar,
|
||
OverBar: OverBar,
|
||
OverBrace: OverBrace,
|
||
OverBracket: OverBracket,
|
||
OverParenthesis: OverParenthesis,
|
||
para: para,
|
||
parallel: parallel,
|
||
par: par,
|
||
parsim: parsim,
|
||
parsl: parsl,
|
||
part: part,
|
||
PartialD: PartialD,
|
||
Pcy: Pcy,
|
||
pcy: pcy,
|
||
percnt: percnt,
|
||
period: period,
|
||
permil: permil,
|
||
perp: perp,
|
||
pertenk: pertenk,
|
||
Pfr: Pfr,
|
||
pfr: pfr,
|
||
Phi: Phi,
|
||
phi: phi,
|
||
phiv: phiv,
|
||
phmmat: phmmat,
|
||
phone: phone,
|
||
Pi: Pi,
|
||
pi: pi,
|
||
pitchfork: pitchfork,
|
||
piv: piv,
|
||
planck: planck,
|
||
planckh: planckh,
|
||
plankv: plankv,
|
||
plusacir: plusacir,
|
||
plusb: plusb,
|
||
pluscir: pluscir,
|
||
plus: plus,
|
||
plusdo: plusdo,
|
||
plusdu: plusdu,
|
||
pluse: pluse,
|
||
PlusMinus: PlusMinus,
|
||
plusmn: plusmn,
|
||
plussim: plussim,
|
||
plustwo: plustwo,
|
||
pm: pm,
|
||
Poincareplane: Poincareplane,
|
||
pointint: pointint,
|
||
popf: popf,
|
||
Popf: Popf,
|
||
pound: pound,
|
||
prap: prap,
|
||
Pr: Pr,
|
||
pr: pr,
|
||
prcue: prcue,
|
||
precapprox: precapprox,
|
||
prec: prec,
|
||
preccurlyeq: preccurlyeq,
|
||
Precedes: Precedes,
|
||
PrecedesEqual: PrecedesEqual,
|
||
PrecedesSlantEqual: PrecedesSlantEqual,
|
||
PrecedesTilde: PrecedesTilde,
|
||
preceq: preceq,
|
||
precnapprox: precnapprox,
|
||
precneqq: precneqq,
|
||
precnsim: precnsim,
|
||
pre: pre,
|
||
prE: prE,
|
||
precsim: precsim,
|
||
prime: prime,
|
||
Prime: Prime,
|
||
primes: primes,
|
||
prnap: prnap,
|
||
prnE: prnE,
|
||
prnsim: prnsim,
|
||
prod: prod,
|
||
Product: Product,
|
||
profalar: profalar,
|
||
profline: profline,
|
||
profsurf: profsurf,
|
||
prop: prop,
|
||
Proportional: Proportional,
|
||
Proportion: Proportion,
|
||
propto: propto,
|
||
prsim: prsim,
|
||
prurel: prurel,
|
||
Pscr: Pscr,
|
||
pscr: pscr,
|
||
Psi: Psi,
|
||
psi: psi,
|
||
puncsp: puncsp,
|
||
Qfr: Qfr,
|
||
qfr: qfr,
|
||
qint: qint,
|
||
qopf: qopf,
|
||
Qopf: Qopf,
|
||
qprime: qprime,
|
||
Qscr: Qscr,
|
||
qscr: qscr,
|
||
quaternions: quaternions,
|
||
quatint: quatint,
|
||
quest: quest,
|
||
questeq: questeq,
|
||
quot: quot,
|
||
QUOT: QUOT,
|
||
rAarr: rAarr,
|
||
race: race,
|
||
Racute: Racute,
|
||
racute: racute,
|
||
radic: radic,
|
||
raemptyv: raemptyv,
|
||
rang: rang,
|
||
Rang: Rang,
|
||
rangd: rangd,
|
||
range: range,
|
||
rangle: rangle,
|
||
raquo: raquo,
|
||
rarrap: rarrap,
|
||
rarrb: rarrb,
|
||
rarrbfs: rarrbfs,
|
||
rarrc: rarrc,
|
||
rarr: rarr,
|
||
Rarr: Rarr,
|
||
rArr: rArr,
|
||
rarrfs: rarrfs,
|
||
rarrhk: rarrhk,
|
||
rarrlp: rarrlp,
|
||
rarrpl: rarrpl,
|
||
rarrsim: rarrsim,
|
||
Rarrtl: Rarrtl,
|
||
rarrtl: rarrtl,
|
||
rarrw: rarrw,
|
||
ratail: ratail,
|
||
rAtail: rAtail,
|
||
ratio: ratio,
|
||
rationals: rationals,
|
||
rbarr: rbarr,
|
||
rBarr: rBarr,
|
||
RBarr: RBarr,
|
||
rbbrk: rbbrk,
|
||
rbrace: rbrace,
|
||
rbrack: rbrack,
|
||
rbrke: rbrke,
|
||
rbrksld: rbrksld,
|
||
rbrkslu: rbrkslu,
|
||
Rcaron: Rcaron,
|
||
rcaron: rcaron,
|
||
Rcedil: Rcedil,
|
||
rcedil: rcedil,
|
||
rceil: rceil,
|
||
rcub: rcub,
|
||
Rcy: Rcy,
|
||
rcy: rcy,
|
||
rdca: rdca,
|
||
rdldhar: rdldhar,
|
||
rdquo: rdquo,
|
||
rdquor: rdquor,
|
||
rdsh: rdsh,
|
||
real: real,
|
||
realine: realine,
|
||
realpart: realpart,
|
||
reals: reals,
|
||
Re: Re,
|
||
rect: rect,
|
||
reg: reg,
|
||
REG: REG,
|
||
ReverseElement: ReverseElement,
|
||
ReverseEquilibrium: ReverseEquilibrium,
|
||
ReverseUpEquilibrium: ReverseUpEquilibrium,
|
||
rfisht: rfisht,
|
||
rfloor: rfloor,
|
||
rfr: rfr,
|
||
Rfr: Rfr,
|
||
rHar: rHar,
|
||
rhard: rhard,
|
||
rharu: rharu,
|
||
rharul: rharul,
|
||
Rho: Rho,
|
||
rho: rho,
|
||
rhov: rhov,
|
||
RightAngleBracket: RightAngleBracket,
|
||
RightArrowBar: RightArrowBar,
|
||
rightarrow: rightarrow,
|
||
RightArrow: RightArrow,
|
||
Rightarrow: Rightarrow,
|
||
RightArrowLeftArrow: RightArrowLeftArrow,
|
||
rightarrowtail: rightarrowtail,
|
||
RightCeiling: RightCeiling,
|
||
RightDoubleBracket: RightDoubleBracket,
|
||
RightDownTeeVector: RightDownTeeVector,
|
||
RightDownVectorBar: RightDownVectorBar,
|
||
RightDownVector: RightDownVector,
|
||
RightFloor: RightFloor,
|
||
rightharpoondown: rightharpoondown,
|
||
rightharpoonup: rightharpoonup,
|
||
rightleftarrows: rightleftarrows,
|
||
rightleftharpoons: rightleftharpoons,
|
||
rightrightarrows: rightrightarrows,
|
||
rightsquigarrow: rightsquigarrow,
|
||
RightTeeArrow: RightTeeArrow,
|
||
RightTee: RightTee,
|
||
RightTeeVector: RightTeeVector,
|
||
rightthreetimes: rightthreetimes,
|
||
RightTriangleBar: RightTriangleBar,
|
||
RightTriangle: RightTriangle,
|
||
RightTriangleEqual: RightTriangleEqual,
|
||
RightUpDownVector: RightUpDownVector,
|
||
RightUpTeeVector: RightUpTeeVector,
|
||
RightUpVectorBar: RightUpVectorBar,
|
||
RightUpVector: RightUpVector,
|
||
RightVectorBar: RightVectorBar,
|
||
RightVector: RightVector,
|
||
ring: ring,
|
||
risingdotseq: risingdotseq,
|
||
rlarr: rlarr,
|
||
rlhar: rlhar,
|
||
rlm: rlm,
|
||
rmoustache: rmoustache,
|
||
rmoust: rmoust,
|
||
rnmid: rnmid,
|
||
roang: roang,
|
||
roarr: roarr,
|
||
robrk: robrk,
|
||
ropar: ropar,
|
||
ropf: ropf,
|
||
Ropf: Ropf,
|
||
roplus: roplus,
|
||
rotimes: rotimes,
|
||
RoundImplies: RoundImplies,
|
||
rpar: rpar,
|
||
rpargt: rpargt,
|
||
rppolint: rppolint,
|
||
rrarr: rrarr,
|
||
Rrightarrow: Rrightarrow,
|
||
rsaquo: rsaquo,
|
||
rscr: rscr,
|
||
Rscr: Rscr,
|
||
rsh: rsh,
|
||
Rsh: Rsh,
|
||
rsqb: rsqb,
|
||
rsquo: rsquo,
|
||
rsquor: rsquor,
|
||
rthree: rthree,
|
||
rtimes: rtimes,
|
||
rtri: rtri,
|
||
rtrie: rtrie,
|
||
rtrif: rtrif,
|
||
rtriltri: rtriltri,
|
||
RuleDelayed: RuleDelayed,
|
||
ruluhar: ruluhar,
|
||
rx: rx,
|
||
Sacute: Sacute,
|
||
sacute: sacute,
|
||
sbquo: sbquo,
|
||
scap: scap,
|
||
Scaron: Scaron,
|
||
scaron: scaron,
|
||
Sc: Sc,
|
||
sc: sc,
|
||
sccue: sccue,
|
||
sce: sce,
|
||
scE: scE,
|
||
Scedil: Scedil,
|
||
scedil: scedil,
|
||
Scirc: Scirc,
|
||
scirc: scirc,
|
||
scnap: scnap,
|
||
scnE: scnE,
|
||
scnsim: scnsim,
|
||
scpolint: scpolint,
|
||
scsim: scsim,
|
||
Scy: Scy,
|
||
scy: scy,
|
||
sdotb: sdotb,
|
||
sdot: sdot,
|
||
sdote: sdote,
|
||
searhk: searhk,
|
||
searr: searr,
|
||
seArr: seArr,
|
||
searrow: searrow,
|
||
sect: sect,
|
||
semi: semi,
|
||
seswar: seswar,
|
||
setminus: setminus,
|
||
setmn: setmn,
|
||
sext: sext,
|
||
Sfr: Sfr,
|
||
sfr: sfr,
|
||
sfrown: sfrown,
|
||
sharp: sharp,
|
||
SHCHcy: SHCHcy,
|
||
shchcy: shchcy,
|
||
SHcy: SHcy,
|
||
shcy: shcy,
|
||
ShortDownArrow: ShortDownArrow,
|
||
ShortLeftArrow: ShortLeftArrow,
|
||
shortmid: shortmid,
|
||
shortparallel: shortparallel,
|
||
ShortRightArrow: ShortRightArrow,
|
||
ShortUpArrow: ShortUpArrow,
|
||
shy: shy,
|
||
Sigma: Sigma,
|
||
sigma: sigma,
|
||
sigmaf: sigmaf,
|
||
sigmav: sigmav,
|
||
sim: sim,
|
||
simdot: simdot,
|
||
sime: sime,
|
||
simeq: simeq,
|
||
simg: simg,
|
||
simgE: simgE,
|
||
siml: siml,
|
||
simlE: simlE,
|
||
simne: simne,
|
||
simplus: simplus,
|
||
simrarr: simrarr,
|
||
slarr: slarr,
|
||
SmallCircle: SmallCircle,
|
||
smallsetminus: smallsetminus,
|
||
smashp: smashp,
|
||
smeparsl: smeparsl,
|
||
smid: smid,
|
||
smile: smile,
|
||
smt: smt,
|
||
smte: smte,
|
||
smtes: smtes,
|
||
SOFTcy: SOFTcy,
|
||
softcy: softcy,
|
||
solbar: solbar,
|
||
solb: solb,
|
||
sol: sol,
|
||
Sopf: Sopf,
|
||
sopf: sopf,
|
||
spades: spades,
|
||
spadesuit: spadesuit,
|
||
spar: spar,
|
||
sqcap: sqcap,
|
||
sqcaps: sqcaps,
|
||
sqcup: sqcup,
|
||
sqcups: sqcups,
|
||
Sqrt: Sqrt,
|
||
sqsub: sqsub,
|
||
sqsube: sqsube,
|
||
sqsubset: sqsubset,
|
||
sqsubseteq: sqsubseteq,
|
||
sqsup: sqsup,
|
||
sqsupe: sqsupe,
|
||
sqsupset: sqsupset,
|
||
sqsupseteq: sqsupseteq,
|
||
square: square,
|
||
Square: Square,
|
||
SquareIntersection: SquareIntersection,
|
||
SquareSubset: SquareSubset,
|
||
SquareSubsetEqual: SquareSubsetEqual,
|
||
SquareSuperset: SquareSuperset,
|
||
SquareSupersetEqual: SquareSupersetEqual,
|
||
SquareUnion: SquareUnion,
|
||
squarf: squarf,
|
||
squ: squ,
|
||
squf: squf,
|
||
srarr: srarr,
|
||
Sscr: Sscr,
|
||
sscr: sscr,
|
||
ssetmn: ssetmn,
|
||
ssmile: ssmile,
|
||
sstarf: sstarf,
|
||
Star: Star,
|
||
star: star,
|
||
starf: starf,
|
||
straightepsilon: straightepsilon,
|
||
straightphi: straightphi,
|
||
strns: strns,
|
||
sub: sub,
|
||
Sub: Sub,
|
||
subdot: subdot,
|
||
subE: subE,
|
||
sube: sube,
|
||
subedot: subedot,
|
||
submult: submult,
|
||
subnE: subnE,
|
||
subne: subne,
|
||
subplus: subplus,
|
||
subrarr: subrarr,
|
||
subset: subset,
|
||
Subset: Subset,
|
||
subseteq: subseteq,
|
||
subseteqq: subseteqq,
|
||
SubsetEqual: SubsetEqual,
|
||
subsetneq: subsetneq,
|
||
subsetneqq: subsetneqq,
|
||
subsim: subsim,
|
||
subsub: subsub,
|
||
subsup: subsup,
|
||
succapprox: succapprox,
|
||
succ: succ,
|
||
succcurlyeq: succcurlyeq,
|
||
Succeeds: Succeeds,
|
||
SucceedsEqual: SucceedsEqual,
|
||
SucceedsSlantEqual: SucceedsSlantEqual,
|
||
SucceedsTilde: SucceedsTilde,
|
||
succeq: succeq,
|
||
succnapprox: succnapprox,
|
||
succneqq: succneqq,
|
||
succnsim: succnsim,
|
||
succsim: succsim,
|
||
SuchThat: SuchThat,
|
||
sum: sum,
|
||
Sum: Sum,
|
||
sung: sung,
|
||
sup1: sup1,
|
||
sup2: sup2,
|
||
sup3: sup3,
|
||
sup: sup,
|
||
Sup: Sup,
|
||
supdot: supdot,
|
||
supdsub: supdsub,
|
||
supE: supE,
|
||
supe: supe,
|
||
supedot: supedot,
|
||
Superset: Superset,
|
||
SupersetEqual: SupersetEqual,
|
||
suphsol: suphsol,
|
||
suphsub: suphsub,
|
||
suplarr: suplarr,
|
||
supmult: supmult,
|
||
supnE: supnE,
|
||
supne: supne,
|
||
supplus: supplus,
|
||
supset: supset,
|
||
Supset: Supset,
|
||
supseteq: supseteq,
|
||
supseteqq: supseteqq,
|
||
supsetneq: supsetneq,
|
||
supsetneqq: supsetneqq,
|
||
supsim: supsim,
|
||
supsub: supsub,
|
||
supsup: supsup,
|
||
swarhk: swarhk,
|
||
swarr: swarr,
|
||
swArr: swArr,
|
||
swarrow: swarrow,
|
||
swnwar: swnwar,
|
||
szlig: szlig,
|
||
Tab: Tab,
|
||
target: target,
|
||
Tau: Tau,
|
||
tau: tau,
|
||
tbrk: tbrk,
|
||
Tcaron: Tcaron,
|
||
tcaron: tcaron,
|
||
Tcedil: Tcedil,
|
||
tcedil: tcedil,
|
||
Tcy: Tcy,
|
||
tcy: tcy,
|
||
tdot: tdot,
|
||
telrec: telrec,
|
||
Tfr: Tfr,
|
||
tfr: tfr,
|
||
there4: there4,
|
||
therefore: therefore,
|
||
Therefore: Therefore,
|
||
Theta: Theta,
|
||
theta: theta,
|
||
thetasym: thetasym,
|
||
thetav: thetav,
|
||
thickapprox: thickapprox,
|
||
thicksim: thicksim,
|
||
ThickSpace: ThickSpace,
|
||
ThinSpace: ThinSpace,
|
||
thinsp: thinsp,
|
||
thkap: thkap,
|
||
thksim: thksim,
|
||
THORN: THORN,
|
||
thorn: thorn,
|
||
tilde: tilde,
|
||
Tilde: Tilde,
|
||
TildeEqual: TildeEqual,
|
||
TildeFullEqual: TildeFullEqual,
|
||
TildeTilde: TildeTilde,
|
||
timesbar: timesbar,
|
||
timesb: timesb,
|
||
times: times,
|
||
timesd: timesd,
|
||
tint: tint,
|
||
toea: toea,
|
||
topbot: topbot,
|
||
topcir: topcir,
|
||
top: top,
|
||
Topf: Topf,
|
||
topf: topf,
|
||
topfork: topfork,
|
||
tosa: tosa,
|
||
tprime: tprime,
|
||
trade: trade,
|
||
TRADE: TRADE,
|
||
triangle: triangle,
|
||
triangledown: triangledown,
|
||
triangleleft: triangleleft,
|
||
trianglelefteq: trianglelefteq,
|
||
triangleq: triangleq,
|
||
triangleright: triangleright,
|
||
trianglerighteq: trianglerighteq,
|
||
tridot: tridot,
|
||
trie: trie,
|
||
triminus: triminus,
|
||
TripleDot: TripleDot,
|
||
triplus: triplus,
|
||
trisb: trisb,
|
||
tritime: tritime,
|
||
trpezium: trpezium,
|
||
Tscr: Tscr,
|
||
tscr: tscr,
|
||
TScy: TScy,
|
||
tscy: tscy,
|
||
TSHcy: TSHcy,
|
||
tshcy: tshcy,
|
||
Tstrok: Tstrok,
|
||
tstrok: tstrok,
|
||
twixt: twixt,
|
||
twoheadleftarrow: twoheadleftarrow,
|
||
twoheadrightarrow: twoheadrightarrow,
|
||
Uacute: Uacute,
|
||
uacute: uacute,
|
||
uarr: uarr,
|
||
Uarr: Uarr,
|
||
uArr: uArr,
|
||
Uarrocir: Uarrocir,
|
||
Ubrcy: Ubrcy,
|
||
ubrcy: ubrcy,
|
||
Ubreve: Ubreve,
|
||
ubreve: ubreve,
|
||
Ucirc: Ucirc,
|
||
ucirc: ucirc,
|
||
Ucy: Ucy,
|
||
ucy: ucy,
|
||
udarr: udarr,
|
||
Udblac: Udblac,
|
||
udblac: udblac,
|
||
udhar: udhar,
|
||
ufisht: ufisht,
|
||
Ufr: Ufr,
|
||
ufr: ufr,
|
||
Ugrave: Ugrave,
|
||
ugrave: ugrave,
|
||
uHar: uHar,
|
||
uharl: uharl,
|
||
uharr: uharr,
|
||
uhblk: uhblk,
|
||
ulcorn: ulcorn,
|
||
ulcorner: ulcorner,
|
||
ulcrop: ulcrop,
|
||
ultri: ultri,
|
||
Umacr: Umacr,
|
||
umacr: umacr,
|
||
uml: uml,
|
||
UnderBar: UnderBar,
|
||
UnderBrace: UnderBrace,
|
||
UnderBracket: UnderBracket,
|
||
UnderParenthesis: UnderParenthesis,
|
||
Union: Union,
|
||
UnionPlus: UnionPlus,
|
||
Uogon: Uogon,
|
||
uogon: uogon,
|
||
Uopf: Uopf,
|
||
uopf: uopf,
|
||
UpArrowBar: UpArrowBar,
|
||
uparrow: uparrow,
|
||
UpArrow: UpArrow,
|
||
Uparrow: Uparrow,
|
||
UpArrowDownArrow: UpArrowDownArrow,
|
||
updownarrow: updownarrow,
|
||
UpDownArrow: UpDownArrow,
|
||
Updownarrow: Updownarrow,
|
||
UpEquilibrium: UpEquilibrium,
|
||
upharpoonleft: upharpoonleft,
|
||
upharpoonright: upharpoonright,
|
||
uplus: uplus,
|
||
UpperLeftArrow: UpperLeftArrow,
|
||
UpperRightArrow: UpperRightArrow,
|
||
upsi: upsi,
|
||
Upsi: Upsi,
|
||
upsih: upsih,
|
||
Upsilon: Upsilon,
|
||
upsilon: upsilon,
|
||
UpTeeArrow: UpTeeArrow,
|
||
UpTee: UpTee,
|
||
upuparrows: upuparrows,
|
||
urcorn: urcorn,
|
||
urcorner: urcorner,
|
||
urcrop: urcrop,
|
||
Uring: Uring,
|
||
uring: uring,
|
||
urtri: urtri,
|
||
Uscr: Uscr,
|
||
uscr: uscr,
|
||
utdot: utdot,
|
||
Utilde: Utilde,
|
||
utilde: utilde,
|
||
utri: utri,
|
||
utrif: utrif,
|
||
uuarr: uuarr,
|
||
Uuml: Uuml,
|
||
uuml: uuml,
|
||
uwangle: uwangle,
|
||
vangrt: vangrt,
|
||
varepsilon: varepsilon,
|
||
varkappa: varkappa,
|
||
varnothing: varnothing,
|
||
varphi: varphi,
|
||
varpi: varpi,
|
||
varpropto: varpropto,
|
||
varr: varr,
|
||
vArr: vArr,
|
||
varrho: varrho,
|
||
varsigma: varsigma,
|
||
varsubsetneq: varsubsetneq,
|
||
varsubsetneqq: varsubsetneqq,
|
||
varsupsetneq: varsupsetneq,
|
||
varsupsetneqq: varsupsetneqq,
|
||
vartheta: vartheta,
|
||
vartriangleleft: vartriangleleft,
|
||
vartriangleright: vartriangleright,
|
||
vBar: vBar,
|
||
Vbar: Vbar,
|
||
vBarv: vBarv,
|
||
Vcy: Vcy,
|
||
vcy: vcy,
|
||
vdash: vdash,
|
||
vDash: vDash,
|
||
Vdash: Vdash,
|
||
VDash: VDash,
|
||
Vdashl: Vdashl,
|
||
veebar: veebar,
|
||
vee: vee,
|
||
Vee: Vee,
|
||
veeeq: veeeq,
|
||
vellip: vellip,
|
||
verbar: verbar,
|
||
Verbar: Verbar,
|
||
vert: vert,
|
||
Vert: Vert,
|
||
VerticalBar: VerticalBar,
|
||
VerticalLine: VerticalLine,
|
||
VerticalSeparator: VerticalSeparator,
|
||
VerticalTilde: VerticalTilde,
|
||
VeryThinSpace: VeryThinSpace,
|
||
Vfr: Vfr,
|
||
vfr: vfr,
|
||
vltri: vltri,
|
||
vnsub: vnsub,
|
||
vnsup: vnsup,
|
||
Vopf: Vopf,
|
||
vopf: vopf,
|
||
vprop: vprop,
|
||
vrtri: vrtri,
|
||
Vscr: Vscr,
|
||
vscr: vscr,
|
||
vsubnE: vsubnE,
|
||
vsubne: vsubne,
|
||
vsupnE: vsupnE,
|
||
vsupne: vsupne,
|
||
Vvdash: Vvdash,
|
||
vzigzag: vzigzag,
|
||
Wcirc: Wcirc,
|
||
wcirc: wcirc,
|
||
wedbar: wedbar,
|
||
wedge: wedge,
|
||
Wedge: Wedge,
|
||
wedgeq: wedgeq,
|
||
weierp: weierp,
|
||
Wfr: Wfr,
|
||
wfr: wfr,
|
||
Wopf: Wopf,
|
||
wopf: wopf,
|
||
wp: wp,
|
||
wr: wr,
|
||
wreath: wreath,
|
||
Wscr: Wscr,
|
||
wscr: wscr,
|
||
xcap: xcap,
|
||
xcirc: xcirc,
|
||
xcup: xcup,
|
||
xdtri: xdtri,
|
||
Xfr: Xfr,
|
||
xfr: xfr,
|
||
xharr: xharr,
|
||
xhArr: xhArr,
|
||
Xi: Xi,
|
||
xi: xi,
|
||
xlarr: xlarr,
|
||
xlArr: xlArr,
|
||
xmap: xmap,
|
||
xnis: xnis,
|
||
xodot: xodot,
|
||
Xopf: Xopf,
|
||
xopf: xopf,
|
||
xoplus: xoplus,
|
||
xotime: xotime,
|
||
xrarr: xrarr,
|
||
xrArr: xrArr,
|
||
Xscr: Xscr,
|
||
xscr: xscr,
|
||
xsqcup: xsqcup,
|
||
xuplus: xuplus,
|
||
xutri: xutri,
|
||
xvee: xvee,
|
||
xwedge: xwedge,
|
||
Yacute: Yacute,
|
||
yacute: yacute,
|
||
YAcy: YAcy,
|
||
yacy: yacy,
|
||
Ycirc: Ycirc,
|
||
ycirc: ycirc,
|
||
Ycy: Ycy,
|
||
ycy: ycy,
|
||
yen: yen,
|
||
Yfr: Yfr,
|
||
yfr: yfr,
|
||
YIcy: YIcy,
|
||
yicy: yicy,
|
||
Yopf: Yopf,
|
||
yopf: yopf,
|
||
Yscr: Yscr,
|
||
yscr: yscr,
|
||
YUcy: YUcy,
|
||
yucy: yucy,
|
||
yuml: yuml,
|
||
Yuml: Yuml,
|
||
Zacute: Zacute,
|
||
zacute: zacute,
|
||
Zcaron: Zcaron,
|
||
zcaron: zcaron,
|
||
Zcy: Zcy,
|
||
zcy: zcy,
|
||
Zdot: Zdot,
|
||
zdot: zdot,
|
||
zeetrf: zeetrf,
|
||
ZeroWidthSpace: ZeroWidthSpace,
|
||
Zeta: Zeta,
|
||
zeta: zeta,
|
||
zfr: zfr,
|
||
Zfr: Zfr,
|
||
ZHcy: ZHcy,
|
||
zhcy: zhcy,
|
||
zigrarr: zigrarr,
|
||
zopf: zopf,
|
||
Zopf: Zopf,
|
||
Zscr: Zscr,
|
||
zscr: zscr,
|
||
zwj: zwj,
|
||
zwnj: zwnj
|
||
};
|
||
|
||
/*eslint quotes:0*/
|
||
var entities$1 = require$$0;
|
||
|
||
var regex$4=/[!-#%-\*,-\/:;\?@\[-\]_\{\}\xA1\xA7\xAB\xB6\xB7\xBB\xBF\u037E\u0387\u055A-\u055F\u0589\u058A\u05BE\u05C0\u05C3\u05C6\u05F3\u05F4\u0609\u060A\u060C\u060D\u061B\u061E\u061F\u066A-\u066D\u06D4\u0700-\u070D\u07F7-\u07F9\u0830-\u083E\u085E\u0964\u0965\u0970\u09FD\u0A76\u0AF0\u0C84\u0DF4\u0E4F\u0E5A\u0E5B\u0F04-\u0F12\u0F14\u0F3A-\u0F3D\u0F85\u0FD0-\u0FD4\u0FD9\u0FDA\u104A-\u104F\u10FB\u1360-\u1368\u1400\u166D\u166E\u169B\u169C\u16EB-\u16ED\u1735\u1736\u17D4-\u17D6\u17D8-\u17DA\u1800-\u180A\u1944\u1945\u1A1E\u1A1F\u1AA0-\u1AA6\u1AA8-\u1AAD\u1B5A-\u1B60\u1BFC-\u1BFF\u1C3B-\u1C3F\u1C7E\u1C7F\u1CC0-\u1CC7\u1CD3\u2010-\u2027\u2030-\u2043\u2045-\u2051\u2053-\u205E\u207D\u207E\u208D\u208E\u2308-\u230B\u2329\u232A\u2768-\u2775\u27C5\u27C6\u27E6-\u27EF\u2983-\u2998\u29D8-\u29DB\u29FC\u29FD\u2CF9-\u2CFC\u2CFE\u2CFF\u2D70\u2E00-\u2E2E\u2E30-\u2E4E\u3001-\u3003\u3008-\u3011\u3014-\u301F\u3030\u303D\u30A0\u30FB\uA4FE\uA4FF\uA60D-\uA60F\uA673\uA67E\uA6F2-\uA6F7\uA874-\uA877\uA8CE\uA8CF\uA8F8-\uA8FA\uA8FC\uA92E\uA92F\uA95F\uA9C1-\uA9CD\uA9DE\uA9DF\uAA5C-\uAA5F\uAADE\uAADF\uAAF0\uAAF1\uABEB\uFD3E\uFD3F\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE61\uFE63\uFE68\uFE6A\uFE6B\uFF01-\uFF03\uFF05-\uFF0A\uFF0C-\uFF0F\uFF1A\uFF1B\uFF1F\uFF20\uFF3B-\uFF3D\uFF3F\uFF5B\uFF5D\uFF5F-\uFF65]|\uD800[\uDD00-\uDD02\uDF9F\uDFD0]|\uD801\uDD6F|\uD802[\uDC57\uDD1F\uDD3F\uDE50-\uDE58\uDE7F\uDEF0-\uDEF6\uDF39-\uDF3F\uDF99-\uDF9C]|\uD803[\uDF55-\uDF59]|\uD804[\uDC47-\uDC4D\uDCBB\uDCBC\uDCBE-\uDCC1\uDD40-\uDD43\uDD74\uDD75\uDDC5-\uDDC8\uDDCD\uDDDB\uDDDD-\uDDDF\uDE38-\uDE3D\uDEA9]|\uD805[\uDC4B-\uDC4F\uDC5B\uDC5D\uDCC6\uDDC1-\uDDD7\uDE41-\uDE43\uDE60-\uDE6C\uDF3C-\uDF3E]|\uD806[\uDC3B\uDE3F-\uDE46\uDE9A-\uDE9C\uDE9E-\uDEA2]|\uD807[\uDC41-\uDC45\uDC70\uDC71\uDEF7\uDEF8]|\uD809[\uDC70-\uDC74]|\uD81A[\uDE6E\uDE6F\uDEF5\uDF37-\uDF3B\uDF44]|\uD81B[\uDE97-\uDE9A]|\uD82F\uDC9F|\uD836[\uDE87-\uDE8B]|\uD83A[\uDD5E\uDD5F]/;
|
||
|
||
var mdurl$1 = {};
|
||
|
||
var encodeCache = {};
|
||
|
||
|
||
// Create a lookup array where anything but characters in `chars` string
|
||
// and alphanumeric chars is percent-encoded.
|
||
//
|
||
function getEncodeCache(exclude) {
|
||
var i, ch, cache = encodeCache[exclude];
|
||
if (cache) { return cache; }
|
||
|
||
cache = encodeCache[exclude] = [];
|
||
|
||
for (i = 0; i < 128; i++) {
|
||
ch = String.fromCharCode(i);
|
||
|
||
if (/^[0-9a-z]$/i.test(ch)) {
|
||
// always allow unencoded alphanumeric characters
|
||
cache.push(ch);
|
||
} else {
|
||
cache.push('%' + ('0' + i.toString(16).toUpperCase()).slice(-2));
|
||
}
|
||
}
|
||
|
||
for (i = 0; i < exclude.length; i++) {
|
||
cache[exclude.charCodeAt(i)] = exclude[i];
|
||
}
|
||
|
||
return cache;
|
||
}
|
||
|
||
|
||
// Encode unsafe characters with percent-encoding, skipping already
|
||
// encoded sequences.
|
||
//
|
||
// - string - string to encode
|
||
// - exclude - list of characters to ignore (in addition to a-zA-Z0-9)
|
||
// - keepEscaped - don't encode '%' in a correct escape sequence (default: true)
|
||
//
|
||
function encode$1(string, exclude, keepEscaped) {
|
||
var i, l, code, nextCode, cache,
|
||
result = '';
|
||
|
||
if (typeof exclude !== 'string') {
|
||
// encode(string, keepEscaped)
|
||
keepEscaped = exclude;
|
||
exclude = encode$1.defaultChars;
|
||
}
|
||
|
||
if (typeof keepEscaped === 'undefined') {
|
||
keepEscaped = true;
|
||
}
|
||
|
||
cache = getEncodeCache(exclude);
|
||
|
||
for (i = 0, l = string.length; i < l; i++) {
|
||
code = string.charCodeAt(i);
|
||
|
||
if (keepEscaped && code === 0x25 /* % */ && i + 2 < l) {
|
||
if (/^[0-9a-f]{2}$/i.test(string.slice(i + 1, i + 3))) {
|
||
result += string.slice(i, i + 3);
|
||
i += 2;
|
||
continue;
|
||
}
|
||
}
|
||
|
||
if (code < 128) {
|
||
result += cache[code];
|
||
continue;
|
||
}
|
||
|
||
if (code >= 0xD800 && code <= 0xDFFF) {
|
||
if (code >= 0xD800 && code <= 0xDBFF && i + 1 < l) {
|
||
nextCode = string.charCodeAt(i + 1);
|
||
if (nextCode >= 0xDC00 && nextCode <= 0xDFFF) {
|
||
result += encodeURIComponent(string[i] + string[i + 1]);
|
||
i++;
|
||
continue;
|
||
}
|
||
}
|
||
result += '%EF%BF%BD';
|
||
continue;
|
||
}
|
||
|
||
result += encodeURIComponent(string[i]);
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
encode$1.defaultChars = ";/?:@&=+$,-_.!~*'()#";
|
||
encode$1.componentChars = "-_.!~*'()";
|
||
|
||
|
||
var encode_1 = encode$1;
|
||
|
||
/* eslint-disable no-bitwise */
|
||
|
||
var decodeCache = {};
|
||
|
||
function getDecodeCache(exclude) {
|
||
var i, ch, cache = decodeCache[exclude];
|
||
if (cache) { return cache; }
|
||
|
||
cache = decodeCache[exclude] = [];
|
||
|
||
for (i = 0; i < 128; i++) {
|
||
ch = String.fromCharCode(i);
|
||
cache.push(ch);
|
||
}
|
||
|
||
for (i = 0; i < exclude.length; i++) {
|
||
ch = exclude.charCodeAt(i);
|
||
cache[ch] = '%' + ('0' + ch.toString(16).toUpperCase()).slice(-2);
|
||
}
|
||
|
||
return cache;
|
||
}
|
||
|
||
|
||
// Decode percent-encoded string.
|
||
//
|
||
function decode$1(string, exclude) {
|
||
var cache;
|
||
|
||
if (typeof exclude !== 'string') {
|
||
exclude = decode$1.defaultChars;
|
||
}
|
||
|
||
cache = getDecodeCache(exclude);
|
||
|
||
return string.replace(/(%[a-f0-9]{2})+/gi, function(seq) {
|
||
var i, l, b1, b2, b3, b4, chr,
|
||
result = '';
|
||
|
||
for (i = 0, l = seq.length; i < l; i += 3) {
|
||
b1 = parseInt(seq.slice(i + 1, i + 3), 16);
|
||
|
||
if (b1 < 0x80) {
|
||
result += cache[b1];
|
||
continue;
|
||
}
|
||
|
||
if ((b1 & 0xE0) === 0xC0 && (i + 3 < l)) {
|
||
// 110xxxxx 10xxxxxx
|
||
b2 = parseInt(seq.slice(i + 4, i + 6), 16);
|
||
|
||
if ((b2 & 0xC0) === 0x80) {
|
||
chr = ((b1 << 6) & 0x7C0) | (b2 & 0x3F);
|
||
|
||
if (chr < 0x80) {
|
||
result += '\ufffd\ufffd';
|
||
} else {
|
||
result += String.fromCharCode(chr);
|
||
}
|
||
|
||
i += 3;
|
||
continue;
|
||
}
|
||
}
|
||
|
||
if ((b1 & 0xF0) === 0xE0 && (i + 6 < l)) {
|
||
// 1110xxxx 10xxxxxx 10xxxxxx
|
||
b2 = parseInt(seq.slice(i + 4, i + 6), 16);
|
||
b3 = parseInt(seq.slice(i + 7, i + 9), 16);
|
||
|
||
if ((b2 & 0xC0) === 0x80 && (b3 & 0xC0) === 0x80) {
|
||
chr = ((b1 << 12) & 0xF000) | ((b2 << 6) & 0xFC0) | (b3 & 0x3F);
|
||
|
||
if (chr < 0x800 || (chr >= 0xD800 && chr <= 0xDFFF)) {
|
||
result += '\ufffd\ufffd\ufffd';
|
||
} else {
|
||
result += String.fromCharCode(chr);
|
||
}
|
||
|
||
i += 6;
|
||
continue;
|
||
}
|
||
}
|
||
|
||
if ((b1 & 0xF8) === 0xF0 && (i + 9 < l)) {
|
||
// 111110xx 10xxxxxx 10xxxxxx 10xxxxxx
|
||
b2 = parseInt(seq.slice(i + 4, i + 6), 16);
|
||
b3 = parseInt(seq.slice(i + 7, i + 9), 16);
|
||
b4 = parseInt(seq.slice(i + 10, i + 12), 16);
|
||
|
||
if ((b2 & 0xC0) === 0x80 && (b3 & 0xC0) === 0x80 && (b4 & 0xC0) === 0x80) {
|
||
chr = ((b1 << 18) & 0x1C0000) | ((b2 << 12) & 0x3F000) | ((b3 << 6) & 0xFC0) | (b4 & 0x3F);
|
||
|
||
if (chr < 0x10000 || chr > 0x10FFFF) {
|
||
result += '\ufffd\ufffd\ufffd\ufffd';
|
||
} else {
|
||
chr -= 0x10000;
|
||
result += String.fromCharCode(0xD800 + (chr >> 10), 0xDC00 + (chr & 0x3FF));
|
||
}
|
||
|
||
i += 9;
|
||
continue;
|
||
}
|
||
}
|
||
|
||
result += '\ufffd';
|
||
}
|
||
|
||
return result;
|
||
});
|
||
}
|
||
|
||
|
||
decode$1.defaultChars = ';/?:@&=+$,#';
|
||
decode$1.componentChars = '';
|
||
|
||
|
||
var decode_1 = decode$1;
|
||
|
||
var format = function format(url) {
|
||
var result = '';
|
||
|
||
result += url.protocol || '';
|
||
result += url.slashes ? '//' : '';
|
||
result += url.auth ? url.auth + '@' : '';
|
||
|
||
if (url.hostname && url.hostname.indexOf(':') !== -1) {
|
||
// ipv6 address
|
||
result += '[' + url.hostname + ']';
|
||
} else {
|
||
result += url.hostname || '';
|
||
}
|
||
|
||
result += url.port ? ':' + url.port : '';
|
||
result += url.pathname || '';
|
||
result += url.search || '';
|
||
result += url.hash || '';
|
||
|
||
return result;
|
||
};
|
||
|
||
//
|
||
// Changes from joyent/node:
|
||
//
|
||
// 1. No leading slash in paths,
|
||
// e.g. in `url.parse('http://foo?bar')` pathname is ``, not `/`
|
||
//
|
||
// 2. Backslashes are not replaced with slashes,
|
||
// so `http:\\example.org\` is treated like a relative path
|
||
//
|
||
// 3. Trailing colon is treated like a part of the path,
|
||
// i.e. in `http://example.org:foo` pathname is `:foo`
|
||
//
|
||
// 4. Nothing is URL-encoded in the resulting object,
|
||
// (in joyent/node some chars in auth and paths are encoded)
|
||
//
|
||
// 5. `url.parse()` does not have `parseQueryString` argument
|
||
//
|
||
// 6. Removed extraneous result properties: `host`, `path`, `query`, etc.,
|
||
// which can be constructed using other parts of the url.
|
||
//
|
||
|
||
|
||
function Url() {
|
||
this.protocol = null;
|
||
this.slashes = null;
|
||
this.auth = null;
|
||
this.port = null;
|
||
this.hostname = null;
|
||
this.hash = null;
|
||
this.search = null;
|
||
this.pathname = null;
|
||
}
|
||
|
||
// Reference: RFC 3986, RFC 1808, RFC 2396
|
||
|
||
// define these here so at least they only have to be
|
||
// compiled once on the first module load.
|
||
var protocolPattern = /^([a-z0-9.+-]+:)/i,
|
||
portPattern = /:[0-9]*$/,
|
||
|
||
// Special case for a simple path URL
|
||
simplePathPattern = /^(\/\/?(?!\/)[^\?\s]*)(\?[^\s]*)?$/,
|
||
|
||
// RFC 2396: characters reserved for delimiting URLs.
|
||
// We actually just auto-escape these.
|
||
delims = [ '<', '>', '"', '`', ' ', '\r', '\n', '\t' ],
|
||
|
||
// RFC 2396: characters not allowed for various reasons.
|
||
unwise = [ '{', '}', '|', '\\', '^', '`' ].concat(delims),
|
||
|
||
// Allowed by RFCs, but cause of XSS attacks. Always escape these.
|
||
autoEscape = [ '\'' ].concat(unwise),
|
||
// Characters that are never ever allowed in a hostname.
|
||
// Note that any invalid chars are also handled, but these
|
||
// are the ones that are *expected* to be seen, so we fast-path
|
||
// them.
|
||
nonHostChars = [ '%', '/', '?', ';', '#' ].concat(autoEscape),
|
||
hostEndingChars = [ '/', '?', '#' ],
|
||
hostnameMaxLen = 255,
|
||
hostnamePartPattern = /^[+a-z0-9A-Z_-]{0,63}$/,
|
||
hostnamePartStart = /^([+a-z0-9A-Z_-]{0,63})(.*)$/,
|
||
// protocols that can allow "unsafe" and "unwise" chars.
|
||
/* eslint-disable no-script-url */
|
||
// protocols that never have a hostname.
|
||
hostlessProtocol = {
|
||
'javascript': true,
|
||
'javascript:': true
|
||
},
|
||
// protocols that always contain a // bit.
|
||
slashedProtocol = {
|
||
'http': true,
|
||
'https': true,
|
||
'ftp': true,
|
||
'gopher': true,
|
||
'file': true,
|
||
'http:': true,
|
||
'https:': true,
|
||
'ftp:': true,
|
||
'gopher:': true,
|
||
'file:': true
|
||
};
|
||
/* eslint-enable no-script-url */
|
||
|
||
function urlParse(url, slashesDenoteHost) {
|
||
if (url && url instanceof Url) { return url; }
|
||
|
||
var u = new Url();
|
||
u.parse(url, slashesDenoteHost);
|
||
return u;
|
||
}
|
||
|
||
Url.prototype.parse = function(url, slashesDenoteHost) {
|
||
var i, l, lowerProto, hec, slashes,
|
||
rest = url;
|
||
|
||
// trim before proceeding.
|
||
// This is to support parse stuff like " http://foo.com \n"
|
||
rest = rest.trim();
|
||
|
||
if (!slashesDenoteHost && url.split('#').length === 1) {
|
||
// Try fast path regexp
|
||
var simplePath = simplePathPattern.exec(rest);
|
||
if (simplePath) {
|
||
this.pathname = simplePath[1];
|
||
if (simplePath[2]) {
|
||
this.search = simplePath[2];
|
||
}
|
||
return this;
|
||
}
|
||
}
|
||
|
||
var proto = protocolPattern.exec(rest);
|
||
if (proto) {
|
||
proto = proto[0];
|
||
lowerProto = proto.toLowerCase();
|
||
this.protocol = proto;
|
||
rest = rest.substr(proto.length);
|
||
}
|
||
|
||
// figure out if it's got a host
|
||
// user@server is *always* interpreted as a hostname, and url
|
||
// resolution will treat //foo/bar as host=foo,path=bar because that's
|
||
// how the browser resolves relative URLs.
|
||
if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) {
|
||
slashes = rest.substr(0, 2) === '//';
|
||
if (slashes && !(proto && hostlessProtocol[proto])) {
|
||
rest = rest.substr(2);
|
||
this.slashes = true;
|
||
}
|
||
}
|
||
|
||
if (!hostlessProtocol[proto] &&
|
||
(slashes || (proto && !slashedProtocol[proto]))) {
|
||
|
||
// there's a hostname.
|
||
// the first instance of /, ?, ;, or # ends the host.
|
||
//
|
||
// If there is an @ in the hostname, then non-host chars *are* allowed
|
||
// to the left of the last @ sign, unless some host-ending character
|
||
// comes *before* the @-sign.
|
||
// URLs are obnoxious.
|
||
//
|
||
// ex:
|
||
// http://a@b@c/ => user:a@b host:c
|
||
// http://a@b?@c => user:a host:c path:/?@c
|
||
|
||
// v0.12 TODO(isaacs): This is not quite how Chrome does things.
|
||
// Review our test case against browsers more comprehensively.
|
||
|
||
// find the first instance of any hostEndingChars
|
||
var hostEnd = -1;
|
||
for (i = 0; i < hostEndingChars.length; i++) {
|
||
hec = rest.indexOf(hostEndingChars[i]);
|
||
if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) {
|
||
hostEnd = hec;
|
||
}
|
||
}
|
||
|
||
// at this point, either we have an explicit point where the
|
||
// auth portion cannot go past, or the last @ char is the decider.
|
||
var auth, atSign;
|
||
if (hostEnd === -1) {
|
||
// atSign can be anywhere.
|
||
atSign = rest.lastIndexOf('@');
|
||
} else {
|
||
// atSign must be in auth portion.
|
||
// http://a@b/c@d => host:b auth:a path:/c@d
|
||
atSign = rest.lastIndexOf('@', hostEnd);
|
||
}
|
||
|
||
// Now we have a portion which is definitely the auth.
|
||
// Pull that off.
|
||
if (atSign !== -1) {
|
||
auth = rest.slice(0, atSign);
|
||
rest = rest.slice(atSign + 1);
|
||
this.auth = auth;
|
||
}
|
||
|
||
// the host is the remaining to the left of the first non-host char
|
||
hostEnd = -1;
|
||
for (i = 0; i < nonHostChars.length; i++) {
|
||
hec = rest.indexOf(nonHostChars[i]);
|
||
if (hec !== -1 && (hostEnd === -1 || hec < hostEnd)) {
|
||
hostEnd = hec;
|
||
}
|
||
}
|
||
// if we still have not hit it, then the entire thing is a host.
|
||
if (hostEnd === -1) {
|
||
hostEnd = rest.length;
|
||
}
|
||
|
||
if (rest[hostEnd - 1] === ':') { hostEnd--; }
|
||
var host = rest.slice(0, hostEnd);
|
||
rest = rest.slice(hostEnd);
|
||
|
||
// pull out port.
|
||
this.parseHost(host);
|
||
|
||
// we've indicated that there is a hostname,
|
||
// so even if it's empty, it has to be present.
|
||
this.hostname = this.hostname || '';
|
||
|
||
// if hostname begins with [ and ends with ]
|
||
// assume that it's an IPv6 address.
|
||
var ipv6Hostname = this.hostname[0] === '[' &&
|
||
this.hostname[this.hostname.length - 1] === ']';
|
||
|
||
// validate a little.
|
||
if (!ipv6Hostname) {
|
||
var hostparts = this.hostname.split(/\./);
|
||
for (i = 0, l = hostparts.length; i < l; i++) {
|
||
var part = hostparts[i];
|
||
if (!part) { continue; }
|
||
if (!part.match(hostnamePartPattern)) {
|
||
var newpart = '';
|
||
for (var j = 0, k = part.length; j < k; j++) {
|
||
if (part.charCodeAt(j) > 127) {
|
||
// we replace non-ASCII char with a temporary placeholder
|
||
// we need this to make sure size of hostname is not
|
||
// broken by replacing non-ASCII by nothing
|
||
newpart += 'x';
|
||
} else {
|
||
newpart += part[j];
|
||
}
|
||
}
|
||
// we test again with ASCII char only
|
||
if (!newpart.match(hostnamePartPattern)) {
|
||
var validParts = hostparts.slice(0, i);
|
||
var notHost = hostparts.slice(i + 1);
|
||
var bit = part.match(hostnamePartStart);
|
||
if (bit) {
|
||
validParts.push(bit[1]);
|
||
notHost.unshift(bit[2]);
|
||
}
|
||
if (notHost.length) {
|
||
rest = notHost.join('.') + rest;
|
||
}
|
||
this.hostname = validParts.join('.');
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (this.hostname.length > hostnameMaxLen) {
|
||
this.hostname = '';
|
||
}
|
||
|
||
// strip [ and ] from the hostname
|
||
// the host field still retains them, though
|
||
if (ipv6Hostname) {
|
||
this.hostname = this.hostname.substr(1, this.hostname.length - 2);
|
||
}
|
||
}
|
||
|
||
// chop off from the tail first.
|
||
var hash = rest.indexOf('#');
|
||
if (hash !== -1) {
|
||
// got a fragment string.
|
||
this.hash = rest.substr(hash);
|
||
rest = rest.slice(0, hash);
|
||
}
|
||
var qm = rest.indexOf('?');
|
||
if (qm !== -1) {
|
||
this.search = rest.substr(qm);
|
||
rest = rest.slice(0, qm);
|
||
}
|
||
if (rest) { this.pathname = rest; }
|
||
if (slashedProtocol[lowerProto] &&
|
||
this.hostname && !this.pathname) {
|
||
this.pathname = '';
|
||
}
|
||
|
||
return this;
|
||
};
|
||
|
||
Url.prototype.parseHost = function(host) {
|
||
var port = portPattern.exec(host);
|
||
if (port) {
|
||
port = port[0];
|
||
if (port !== ':') {
|
||
this.port = port.substr(1);
|
||
}
|
||
host = host.substr(0, host.length - port.length);
|
||
}
|
||
if (host) { this.hostname = host; }
|
||
};
|
||
|
||
var parse = urlParse;
|
||
|
||
mdurl$1.encode = encode_1;
|
||
mdurl$1.decode = decode_1;
|
||
mdurl$1.format = format;
|
||
mdurl$1.parse = parse;
|
||
|
||
var uc_micro = {};
|
||
|
||
var regex$3=/[\0-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/;
|
||
|
||
var regex$2=/[\0-\x1F\x7F-\x9F]/;
|
||
|
||
var regex$1=/[\xAD\u0600-\u0605\u061C\u06DD\u070F\u08E2\u180E\u200B-\u200F\u202A-\u202E\u2060-\u2064\u2066-\u206F\uFEFF\uFFF9-\uFFFB]|\uD804[\uDCBD\uDCCD]|\uD82F[\uDCA0-\uDCA3]|\uD834[\uDD73-\uDD7A]|\uDB40[\uDC01\uDC20-\uDC7F]/;
|
||
|
||
var regex=/[ \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]/;
|
||
|
||
uc_micro.Any = regex$3;
|
||
uc_micro.Cc = regex$2;
|
||
uc_micro.Cf = regex$1;
|
||
uc_micro.P = regex$4;
|
||
uc_micro.Z = regex;
|
||
|
||
(function (exports) {
|
||
|
||
|
||
function _class(obj) { return Object.prototype.toString.call(obj); }
|
||
|
||
function isString(obj) { return _class(obj) === '[object String]'; }
|
||
|
||
var _hasOwnProperty = Object.prototype.hasOwnProperty;
|
||
|
||
function has(object, key) {
|
||
return _hasOwnProperty.call(object, key);
|
||
}
|
||
|
||
// Merge objects
|
||
//
|
||
function assign(obj /*from1, from2, from3, ...*/) {
|
||
var sources = Array.prototype.slice.call(arguments, 1);
|
||
|
||
sources.forEach(function (source) {
|
||
if (!source) { return; }
|
||
|
||
if (typeof source !== 'object') {
|
||
throw new TypeError(source + 'must be object');
|
||
}
|
||
|
||
Object.keys(source).forEach(function (key) {
|
||
obj[key] = source[key];
|
||
});
|
||
});
|
||
|
||
return obj;
|
||
}
|
||
|
||
// Remove element from array and put another array at those position.
|
||
// Useful for some operations with tokens
|
||
function arrayReplaceAt(src, pos, newElements) {
|
||
return [].concat(src.slice(0, pos), newElements, src.slice(pos + 1));
|
||
}
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
|
||
function isValidEntityCode(c) {
|
||
/*eslint no-bitwise:0*/
|
||
// broken sequence
|
||
if (c >= 0xD800 && c <= 0xDFFF) { return false; }
|
||
// never used
|
||
if (c >= 0xFDD0 && c <= 0xFDEF) { return false; }
|
||
if ((c & 0xFFFF) === 0xFFFF || (c & 0xFFFF) === 0xFFFE) { return false; }
|
||
// control codes
|
||
if (c >= 0x00 && c <= 0x08) { return false; }
|
||
if (c === 0x0B) { return false; }
|
||
if (c >= 0x0E && c <= 0x1F) { return false; }
|
||
if (c >= 0x7F && c <= 0x9F) { return false; }
|
||
// out of range
|
||
if (c > 0x10FFFF) { return false; }
|
||
return true;
|
||
}
|
||
|
||
function fromCodePoint(c) {
|
||
/*eslint no-bitwise:0*/
|
||
if (c > 0xffff) {
|
||
c -= 0x10000;
|
||
var surrogate1 = 0xd800 + (c >> 10),
|
||
surrogate2 = 0xdc00 + (c & 0x3ff);
|
||
|
||
return String.fromCharCode(surrogate1, surrogate2);
|
||
}
|
||
return String.fromCharCode(c);
|
||
}
|
||
|
||
|
||
var UNESCAPE_MD_RE = /\\([!"#$%&'()*+,\-.\/:;<=>?@[\\\]^_`{|}~])/g;
|
||
var ENTITY_RE = /&([a-z#][a-z0-9]{1,31});/gi;
|
||
var UNESCAPE_ALL_RE = new RegExp(UNESCAPE_MD_RE.source + '|' + ENTITY_RE.source, 'gi');
|
||
|
||
var DIGITAL_ENTITY_TEST_RE = /^#((?:x[a-f0-9]{1,8}|[0-9]{1,8}))/i;
|
||
|
||
var entities = entities$1;
|
||
|
||
function replaceEntityPattern(match, name) {
|
||
var code = 0;
|
||
|
||
if (has(entities, name)) {
|
||
return entities[name];
|
||
}
|
||
|
||
if (name.charCodeAt(0) === 0x23/* # */ && DIGITAL_ENTITY_TEST_RE.test(name)) {
|
||
code = name[1].toLowerCase() === 'x' ?
|
||
parseInt(name.slice(2), 16) : parseInt(name.slice(1), 10);
|
||
|
||
if (isValidEntityCode(code)) {
|
||
return fromCodePoint(code);
|
||
}
|
||
}
|
||
|
||
return match;
|
||
}
|
||
|
||
/*function replaceEntities(str) {
|
||
if (str.indexOf('&') < 0) { return str; }
|
||
|
||
return str.replace(ENTITY_RE, replaceEntityPattern);
|
||
}*/
|
||
|
||
function unescapeMd(str) {
|
||
if (str.indexOf('\\') < 0) { return str; }
|
||
return str.replace(UNESCAPE_MD_RE, '$1');
|
||
}
|
||
|
||
function unescapeAll(str) {
|
||
if (str.indexOf('\\') < 0 && str.indexOf('&') < 0) { return str; }
|
||
|
||
return str.replace(UNESCAPE_ALL_RE, function (match, escaped, entity) {
|
||
if (escaped) { return escaped; }
|
||
return replaceEntityPattern(match, entity);
|
||
});
|
||
}
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
|
||
var HTML_ESCAPE_TEST_RE = /[&<>"]/;
|
||
var HTML_ESCAPE_REPLACE_RE = /[&<>"]/g;
|
||
var HTML_REPLACEMENTS = {
|
||
'&': '&',
|
||
'<': '<',
|
||
'>': '>',
|
||
'"': '"'
|
||
};
|
||
|
||
function replaceUnsafeChar(ch) {
|
||
return HTML_REPLACEMENTS[ch];
|
||
}
|
||
|
||
function escapeHtml(str) {
|
||
if (HTML_ESCAPE_TEST_RE.test(str)) {
|
||
return str.replace(HTML_ESCAPE_REPLACE_RE, replaceUnsafeChar);
|
||
}
|
||
return str;
|
||
}
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
|
||
var REGEXP_ESCAPE_RE = /[.?*+^$[\]\\(){}|-]/g;
|
||
|
||
function escapeRE(str) {
|
||
return str.replace(REGEXP_ESCAPE_RE, '\\$&');
|
||
}
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
|
||
function isSpace(code) {
|
||
switch (code) {
|
||
case 0x09:
|
||
case 0x20:
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
// Zs (unicode class) || [\t\f\v\r\n]
|
||
function isWhiteSpace(code) {
|
||
if (code >= 0x2000 && code <= 0x200A) { return true; }
|
||
switch (code) {
|
||
case 0x09: // \t
|
||
case 0x0A: // \n
|
||
case 0x0B: // \v
|
||
case 0x0C: // \f
|
||
case 0x0D: // \r
|
||
case 0x20:
|
||
case 0xA0:
|
||
case 0x1680:
|
||
case 0x202F:
|
||
case 0x205F:
|
||
case 0x3000:
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
|
||
/*eslint-disable max-len*/
|
||
var UNICODE_PUNCT_RE = regex$4;
|
||
|
||
// Currently without astral characters support.
|
||
function isPunctChar(ch) {
|
||
return UNICODE_PUNCT_RE.test(ch);
|
||
}
|
||
|
||
|
||
// Markdown ASCII punctuation characters.
|
||
//
|
||
// !, ", #, $, %, &, ', (, ), *, +, ,, -, ., /, :, ;, <, =, >, ?, @, [, \, ], ^, _, `, {, |, }, or ~
|
||
// http://spec.commonmark.org/0.15/#ascii-punctuation-character
|
||
//
|
||
// Don't confuse with unicode punctuation !!! It lacks some chars in ascii range.
|
||
//
|
||
function isMdAsciiPunct(ch) {
|
||
switch (ch) {
|
||
case 0x21/* ! */:
|
||
case 0x22/* " */:
|
||
case 0x23/* # */:
|
||
case 0x24/* $ */:
|
||
case 0x25/* % */:
|
||
case 0x26/* & */:
|
||
case 0x27/* ' */:
|
||
case 0x28/* ( */:
|
||
case 0x29/* ) */:
|
||
case 0x2A/* * */:
|
||
case 0x2B/* + */:
|
||
case 0x2C/* , */:
|
||
case 0x2D/* - */:
|
||
case 0x2E/* . */:
|
||
case 0x2F/* / */:
|
||
case 0x3A/* : */:
|
||
case 0x3B/* ; */:
|
||
case 0x3C/* < */:
|
||
case 0x3D/* = */:
|
||
case 0x3E/* > */:
|
||
case 0x3F/* ? */:
|
||
case 0x40/* @ */:
|
||
case 0x5B/* [ */:
|
||
case 0x5C/* \ */:
|
||
case 0x5D/* ] */:
|
||
case 0x5E/* ^ */:
|
||
case 0x5F/* _ */:
|
||
case 0x60/* ` */:
|
||
case 0x7B/* { */:
|
||
case 0x7C/* | */:
|
||
case 0x7D/* } */:
|
||
case 0x7E/* ~ */:
|
||
return true;
|
||
default:
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// Hepler to unify [reference labels].
|
||
//
|
||
function normalizeReference(str) {
|
||
// Trim and collapse whitespace
|
||
//
|
||
str = str.trim().replace(/\s+/g, ' ');
|
||
|
||
// In node v10 'ẞ'.toLowerCase() === 'Ṿ', which is presumed to be a bug
|
||
// fixed in v12 (couldn't find any details).
|
||
//
|
||
// So treat this one as a special case
|
||
// (remove this when node v10 is no longer supported).
|
||
//
|
||
if ('ẞ'.toLowerCase() === 'Ṿ') {
|
||
str = str.replace(/ẞ/g, 'ß');
|
||
}
|
||
|
||
// .toLowerCase().toUpperCase() should get rid of all differences
|
||
// between letter variants.
|
||
//
|
||
// Simple .toLowerCase() doesn't normalize 125 code points correctly,
|
||
// and .toUpperCase doesn't normalize 6 of them (list of exceptions:
|
||
// İ, ϴ, ẞ, Ω, K, Å - those are already uppercased, but have differently
|
||
// uppercased versions).
|
||
//
|
||
// Here's an example showing how it happens. Lets take greek letter omega:
|
||
// uppercase U+0398 (Θ), U+03f4 (ϴ) and lowercase U+03b8 (θ), U+03d1 (ϑ)
|
||
//
|
||
// Unicode entries:
|
||
// 0398;GREEK CAPITAL LETTER THETA;Lu;0;L;;;;;N;;;;03B8;
|
||
// 03B8;GREEK SMALL LETTER THETA;Ll;0;L;;;;;N;;;0398;;0398
|
||
// 03D1;GREEK THETA SYMBOL;Ll;0;L;<compat> 03B8;;;;N;GREEK SMALL LETTER SCRIPT THETA;;0398;;0398
|
||
// 03F4;GREEK CAPITAL THETA SYMBOL;Lu;0;L;<compat> 0398;;;;N;;;;03B8;
|
||
//
|
||
// Case-insensitive comparison should treat all of them as equivalent.
|
||
//
|
||
// But .toLowerCase() doesn't change ϑ (it's already lowercase),
|
||
// and .toUpperCase() doesn't change ϴ (already uppercase).
|
||
//
|
||
// Applying first lower then upper case normalizes any character:
|
||
// '\u0398\u03f4\u03b8\u03d1'.toLowerCase().toUpperCase() === '\u0398\u0398\u0398\u0398'
|
||
//
|
||
// Note: this is equivalent to unicode case folding; unicode normalization
|
||
// is a different step that is not required here.
|
||
//
|
||
// Final result should be uppercased, because it's later stored in an object
|
||
// (this avoid a conflict with Object.prototype members,
|
||
// most notably, `__proto__`)
|
||
//
|
||
return str.toLowerCase().toUpperCase();
|
||
}
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
|
||
// Re-export libraries commonly used in both markdown-it and its plugins,
|
||
// so plugins won't have to depend on them explicitly, which reduces their
|
||
// bundled size (e.g. a browser build).
|
||
//
|
||
exports.lib = {};
|
||
exports.lib.mdurl = mdurl$1;
|
||
exports.lib.ucmicro = uc_micro;
|
||
|
||
exports.assign = assign;
|
||
exports.isString = isString;
|
||
exports.has = has;
|
||
exports.unescapeMd = unescapeMd;
|
||
exports.unescapeAll = unescapeAll;
|
||
exports.isValidEntityCode = isValidEntityCode;
|
||
exports.fromCodePoint = fromCodePoint;
|
||
// exports.replaceEntities = replaceEntities;
|
||
exports.escapeHtml = escapeHtml;
|
||
exports.arrayReplaceAt = arrayReplaceAt;
|
||
exports.isSpace = isSpace;
|
||
exports.isWhiteSpace = isWhiteSpace;
|
||
exports.isMdAsciiPunct = isMdAsciiPunct;
|
||
exports.isPunctChar = isPunctChar;
|
||
exports.escapeRE = escapeRE;
|
||
exports.normalizeReference = normalizeReference;
|
||
}(utils$1));
|
||
|
||
var helpers$1 = {};
|
||
|
||
var parse_link_label = function parseLinkLabel(state, start, disableNested) {
|
||
var level, found, marker, prevPos,
|
||
labelEnd = -1,
|
||
max = state.posMax,
|
||
oldPos = state.pos;
|
||
|
||
state.pos = start + 1;
|
||
level = 1;
|
||
|
||
while (state.pos < max) {
|
||
marker = state.src.charCodeAt(state.pos);
|
||
if (marker === 0x5D /* ] */) {
|
||
level--;
|
||
if (level === 0) {
|
||
found = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
prevPos = state.pos;
|
||
state.md.inline.skipToken(state);
|
||
if (marker === 0x5B /* [ */) {
|
||
if (prevPos === state.pos - 1) {
|
||
// increase level if we find text `[`, which is not a part of any token
|
||
level++;
|
||
} else if (disableNested) {
|
||
state.pos = oldPos;
|
||
return -1;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (found) {
|
||
labelEnd = state.pos;
|
||
}
|
||
|
||
// restore old state
|
||
state.pos = oldPos;
|
||
|
||
return labelEnd;
|
||
};
|
||
|
||
var unescapeAll$2 = utils$1.unescapeAll;
|
||
|
||
|
||
var parse_link_destination = function parseLinkDestination(str, pos, max) {
|
||
var code, level,
|
||
lines = 0,
|
||
start = pos,
|
||
result = {
|
||
ok: false,
|
||
pos: 0,
|
||
lines: 0,
|
||
str: ''
|
||
};
|
||
|
||
if (str.charCodeAt(pos) === 0x3C /* < */) {
|
||
pos++;
|
||
while (pos < max) {
|
||
code = str.charCodeAt(pos);
|
||
if (code === 0x0A /* \n */) { return result; }
|
||
if (code === 0x3C /* < */) { return result; }
|
||
if (code === 0x3E /* > */) {
|
||
result.pos = pos + 1;
|
||
result.str = unescapeAll$2(str.slice(start + 1, pos));
|
||
result.ok = true;
|
||
return result;
|
||
}
|
||
if (code === 0x5C /* \ */ && pos + 1 < max) {
|
||
pos += 2;
|
||
continue;
|
||
}
|
||
|
||
pos++;
|
||
}
|
||
|
||
// no closing '>'
|
||
return result;
|
||
}
|
||
|
||
// this should be ... } else { ... branch
|
||
|
||
level = 0;
|
||
while (pos < max) {
|
||
code = str.charCodeAt(pos);
|
||
|
||
if (code === 0x20) { break; }
|
||
|
||
// ascii control characters
|
||
if (code < 0x20 || code === 0x7F) { break; }
|
||
|
||
if (code === 0x5C /* \ */ && pos + 1 < max) {
|
||
if (str.charCodeAt(pos + 1) === 0x20) { break; }
|
||
pos += 2;
|
||
continue;
|
||
}
|
||
|
||
if (code === 0x28 /* ( */) {
|
||
level++;
|
||
if (level > 32) { return result; }
|
||
}
|
||
|
||
if (code === 0x29 /* ) */) {
|
||
if (level === 0) { break; }
|
||
level--;
|
||
}
|
||
|
||
pos++;
|
||
}
|
||
|
||
if (start === pos) { return result; }
|
||
if (level !== 0) { return result; }
|
||
|
||
result.str = unescapeAll$2(str.slice(start, pos));
|
||
result.lines = lines;
|
||
result.pos = pos;
|
||
result.ok = true;
|
||
return result;
|
||
};
|
||
|
||
var unescapeAll$1 = utils$1.unescapeAll;
|
||
|
||
|
||
var parse_link_title = function parseLinkTitle(str, pos, max) {
|
||
var code,
|
||
marker,
|
||
lines = 0,
|
||
start = pos,
|
||
result = {
|
||
ok: false,
|
||
pos: 0,
|
||
lines: 0,
|
||
str: ''
|
||
};
|
||
|
||
if (pos >= max) { return result; }
|
||
|
||
marker = str.charCodeAt(pos);
|
||
|
||
if (marker !== 0x22 /* " */ && marker !== 0x27 /* ' */ && marker !== 0x28 /* ( */) { return result; }
|
||
|
||
pos++;
|
||
|
||
// if opening marker is "(", switch it to closing marker ")"
|
||
if (marker === 0x28) { marker = 0x29; }
|
||
|
||
while (pos < max) {
|
||
code = str.charCodeAt(pos);
|
||
if (code === marker) {
|
||
result.pos = pos + 1;
|
||
result.lines = lines;
|
||
result.str = unescapeAll$1(str.slice(start + 1, pos));
|
||
result.ok = true;
|
||
return result;
|
||
} else if (code === 0x28 /* ( */ && marker === 0x29 /* ) */) {
|
||
return result;
|
||
} else if (code === 0x0A) {
|
||
lines++;
|
||
} else if (code === 0x5C /* \ */ && pos + 1 < max) {
|
||
pos++;
|
||
if (str.charCodeAt(pos) === 0x0A) {
|
||
lines++;
|
||
}
|
||
}
|
||
|
||
pos++;
|
||
}
|
||
|
||
return result;
|
||
};
|
||
|
||
helpers$1.parseLinkLabel = parse_link_label;
|
||
helpers$1.parseLinkDestination = parse_link_destination;
|
||
helpers$1.parseLinkTitle = parse_link_title;
|
||
|
||
/**
|
||
* class Renderer
|
||
*
|
||
* Generates HTML from parsed token stream. Each instance has independent
|
||
* copy of rules. Those can be rewritten with ease. Also, you can add new
|
||
* rules if you create plugin and adds new token types.
|
||
**/
|
||
|
||
|
||
var assign$1 = utils$1.assign;
|
||
var unescapeAll = utils$1.unescapeAll;
|
||
var escapeHtml = utils$1.escapeHtml;
|
||
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
|
||
var default_rules = {};
|
||
|
||
|
||
default_rules.code_inline = function (tokens, idx, options, env, slf) {
|
||
var token = tokens[idx];
|
||
|
||
return '<code' + slf.renderAttrs(token) + '>' +
|
||
escapeHtml(tokens[idx].content) +
|
||
'</code>';
|
||
};
|
||
|
||
|
||
default_rules.code_block = function (tokens, idx, options, env, slf) {
|
||
var token = tokens[idx];
|
||
|
||
return '<pre' + slf.renderAttrs(token) + '><code>' +
|
||
escapeHtml(tokens[idx].content) +
|
||
'</code></pre>\n';
|
||
};
|
||
|
||
|
||
default_rules.fence = function (tokens, idx, options, env, slf) {
|
||
var token = tokens[idx],
|
||
info = token.info ? unescapeAll(token.info).trim() : '',
|
||
langName = '',
|
||
langAttrs = '',
|
||
highlighted, i, arr, tmpAttrs, tmpToken;
|
||
|
||
if (info) {
|
||
arr = info.split(/(\s+)/g);
|
||
langName = arr[0];
|
||
langAttrs = arr.slice(2).join('');
|
||
}
|
||
|
||
if (options.highlight) {
|
||
highlighted = options.highlight(token.content, langName, langAttrs) || escapeHtml(token.content);
|
||
} else {
|
||
highlighted = escapeHtml(token.content);
|
||
}
|
||
|
||
if (highlighted.indexOf('<pre') === 0) {
|
||
return highlighted + '\n';
|
||
}
|
||
|
||
// If language exists, inject class gently, without modifying original token.
|
||
// May be, one day we will add .deepClone() for token and simplify this part, but
|
||
// now we prefer to keep things local.
|
||
if (info) {
|
||
i = token.attrIndex('class');
|
||
tmpAttrs = token.attrs ? token.attrs.slice() : [];
|
||
|
||
if (i < 0) {
|
||
tmpAttrs.push([ 'class', options.langPrefix + langName ]);
|
||
} else {
|
||
tmpAttrs[i] = tmpAttrs[i].slice();
|
||
tmpAttrs[i][1] += ' ' + options.langPrefix + langName;
|
||
}
|
||
|
||
// Fake token just to render attributes
|
||
tmpToken = {
|
||
attrs: tmpAttrs
|
||
};
|
||
|
||
return '<pre><code' + slf.renderAttrs(tmpToken) + '>'
|
||
+ highlighted
|
||
+ '</code></pre>\n';
|
||
}
|
||
|
||
|
||
return '<pre><code' + slf.renderAttrs(token) + '>'
|
||
+ highlighted
|
||
+ '</code></pre>\n';
|
||
};
|
||
|
||
|
||
default_rules.image = function (tokens, idx, options, env, slf) {
|
||
var token = tokens[idx];
|
||
|
||
// "alt" attr MUST be set, even if empty. Because it's mandatory and
|
||
// should be placed on proper position for tests.
|
||
//
|
||
// Replace content with actual value
|
||
|
||
token.attrs[token.attrIndex('alt')][1] =
|
||
slf.renderInlineAsText(token.children, options, env);
|
||
|
||
return slf.renderToken(tokens, idx, options);
|
||
};
|
||
|
||
|
||
default_rules.hardbreak = function (tokens, idx, options /*, env */) {
|
||
return options.xhtmlOut ? '<br />\n' : '<br>\n';
|
||
};
|
||
default_rules.softbreak = function (tokens, idx, options /*, env */) {
|
||
return options.breaks ? (options.xhtmlOut ? '<br />\n' : '<br>\n') : '\n';
|
||
};
|
||
|
||
|
||
default_rules.text = function (tokens, idx /*, options, env */) {
|
||
return escapeHtml(tokens[idx].content);
|
||
};
|
||
|
||
|
||
default_rules.html_block = function (tokens, idx /*, options, env */) {
|
||
return tokens[idx].content;
|
||
};
|
||
default_rules.html_inline = function (tokens, idx /*, options, env */) {
|
||
return tokens[idx].content;
|
||
};
|
||
|
||
|
||
/**
|
||
* new Renderer()
|
||
*
|
||
* Creates new [[Renderer]] instance and fill [[Renderer#rules]] with defaults.
|
||
**/
|
||
function Renderer$1() {
|
||
|
||
/**
|
||
* Renderer#rules -> Object
|
||
*
|
||
* Contains render rules for tokens. Can be updated and extended.
|
||
*
|
||
* ##### Example
|
||
*
|
||
* ```javascript
|
||
* var md = require('markdown-it')();
|
||
*
|
||
* md.renderer.rules.strong_open = function () { return '<b>'; };
|
||
* md.renderer.rules.strong_close = function () { return '</b>'; };
|
||
*
|
||
* var result = md.renderInline(...);
|
||
* ```
|
||
*
|
||
* Each rule is called as independent static function with fixed signature:
|
||
*
|
||
* ```javascript
|
||
* function my_token_render(tokens, idx, options, env, renderer) {
|
||
* // ...
|
||
* return renderedHTML;
|
||
* }
|
||
* ```
|
||
*
|
||
* See [source code](https://github.com/markdown-it/markdown-it/blob/master/lib/renderer.js)
|
||
* for more details and examples.
|
||
**/
|
||
this.rules = assign$1({}, default_rules);
|
||
}
|
||
|
||
|
||
/**
|
||
* Renderer.renderAttrs(token) -> String
|
||
*
|
||
* Render token attributes to string.
|
||
**/
|
||
Renderer$1.prototype.renderAttrs = function renderAttrs(token) {
|
||
var i, l, result;
|
||
|
||
if (!token.attrs) { return ''; }
|
||
|
||
result = '';
|
||
|
||
for (i = 0, l = token.attrs.length; i < l; i++) {
|
||
result += ' ' + escapeHtml(token.attrs[i][0]) + '="' + escapeHtml(token.attrs[i][1]) + '"';
|
||
}
|
||
|
||
return result;
|
||
};
|
||
|
||
|
||
/**
|
||
* Renderer.renderToken(tokens, idx, options) -> String
|
||
* - tokens (Array): list of tokens
|
||
* - idx (Numbed): token index to render
|
||
* - options (Object): params of parser instance
|
||
*
|
||
* Default token renderer. Can be overriden by custom function
|
||
* in [[Renderer#rules]].
|
||
**/
|
||
Renderer$1.prototype.renderToken = function renderToken(tokens, idx, options) {
|
||
var nextToken,
|
||
result = '',
|
||
needLf = false,
|
||
token = tokens[idx];
|
||
|
||
// Tight list paragraphs
|
||
if (token.hidden) {
|
||
return '';
|
||
}
|
||
|
||
// Insert a newline between hidden paragraph and subsequent opening
|
||
// block-level tag.
|
||
//
|
||
// For example, here we should insert a newline before blockquote:
|
||
// - a
|
||
// >
|
||
//
|
||
if (token.block && token.nesting !== -1 && idx && tokens[idx - 1].hidden) {
|
||
result += '\n';
|
||
}
|
||
|
||
// Add token name, e.g. `<img`
|
||
result += (token.nesting === -1 ? '</' : '<') + token.tag;
|
||
|
||
// Encode attributes, e.g. `<img src="foo"`
|
||
result += this.renderAttrs(token);
|
||
|
||
// Add a slash for self-closing tags, e.g. `<img src="foo" /`
|
||
if (token.nesting === 0 && options.xhtmlOut) {
|
||
result += ' /';
|
||
}
|
||
|
||
// Check if we need to add a newline after this tag
|
||
if (token.block) {
|
||
needLf = true;
|
||
|
||
if (token.nesting === 1) {
|
||
if (idx + 1 < tokens.length) {
|
||
nextToken = tokens[idx + 1];
|
||
|
||
if (nextToken.type === 'inline' || nextToken.hidden) {
|
||
// Block-level tag containing an inline tag.
|
||
//
|
||
needLf = false;
|
||
|
||
} else if (nextToken.nesting === -1 && nextToken.tag === token.tag) {
|
||
// Opening tag + closing tag of the same type. E.g. `<li></li>`.
|
||
//
|
||
needLf = false;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
result += needLf ? '>\n' : '>';
|
||
|
||
return result;
|
||
};
|
||
|
||
|
||
/**
|
||
* Renderer.renderInline(tokens, options, env) -> String
|
||
* - tokens (Array): list on block tokens to render
|
||
* - options (Object): params of parser instance
|
||
* - env (Object): additional data from parsed input (references, for example)
|
||
*
|
||
* The same as [[Renderer.render]], but for single token of `inline` type.
|
||
**/
|
||
Renderer$1.prototype.renderInline = function (tokens, options, env) {
|
||
var type,
|
||
result = '',
|
||
rules = this.rules;
|
||
|
||
for (var i = 0, len = tokens.length; i < len; i++) {
|
||
type = tokens[i].type;
|
||
|
||
if (typeof rules[type] !== 'undefined') {
|
||
result += rules[type](tokens, i, options, env, this);
|
||
} else {
|
||
result += this.renderToken(tokens, i, options);
|
||
}
|
||
}
|
||
|
||
return result;
|
||
};
|
||
|
||
|
||
/** internal
|
||
* Renderer.renderInlineAsText(tokens, options, env) -> String
|
||
* - tokens (Array): list on block tokens to render
|
||
* - options (Object): params of parser instance
|
||
* - env (Object): additional data from parsed input (references, for example)
|
||
*
|
||
* Special kludge for image `alt` attributes to conform CommonMark spec.
|
||
* Don't try to use it! Spec requires to show `alt` content with stripped markup,
|
||
* instead of simple escaping.
|
||
**/
|
||
Renderer$1.prototype.renderInlineAsText = function (tokens, options, env) {
|
||
var result = '';
|
||
|
||
for (var i = 0, len = tokens.length; i < len; i++) {
|
||
if (tokens[i].type === 'text') {
|
||
result += tokens[i].content;
|
||
} else if (tokens[i].type === 'image') {
|
||
result += this.renderInlineAsText(tokens[i].children, options, env);
|
||
} else if (tokens[i].type === 'softbreak') {
|
||
result += '\n';
|
||
}
|
||
}
|
||
|
||
return result;
|
||
};
|
||
|
||
|
||
/**
|
||
* Renderer.render(tokens, options, env) -> String
|
||
* - tokens (Array): list on block tokens to render
|
||
* - options (Object): params of parser instance
|
||
* - env (Object): additional data from parsed input (references, for example)
|
||
*
|
||
* Takes token stream and generates HTML. Probably, you will never need to call
|
||
* this method directly.
|
||
**/
|
||
Renderer$1.prototype.render = function (tokens, options, env) {
|
||
var i, len, type,
|
||
result = '',
|
||
rules = this.rules;
|
||
|
||
for (i = 0, len = tokens.length; i < len; i++) {
|
||
type = tokens[i].type;
|
||
|
||
if (type === 'inline') {
|
||
result += this.renderInline(tokens[i].children, options, env);
|
||
} else if (typeof rules[type] !== 'undefined') {
|
||
result += rules[tokens[i].type](tokens, i, options, env, this);
|
||
} else {
|
||
result += this.renderToken(tokens, i, options, env);
|
||
}
|
||
}
|
||
|
||
return result;
|
||
};
|
||
|
||
var renderer = Renderer$1;
|
||
|
||
/**
|
||
* class Ruler
|
||
*
|
||
* Helper class, used by [[MarkdownIt#core]], [[MarkdownIt#block]] and
|
||
* [[MarkdownIt#inline]] to manage sequences of functions (rules):
|
||
*
|
||
* - keep rules in defined order
|
||
* - assign the name to each rule
|
||
* - enable/disable rules
|
||
* - add/replace rules
|
||
* - allow assign rules to additional named chains (in the same)
|
||
* - cacheing lists of active rules
|
||
*
|
||
* You will not need use this class directly until write plugins. For simple
|
||
* rules control use [[MarkdownIt.disable]], [[MarkdownIt.enable]] and
|
||
* [[MarkdownIt.use]].
|
||
**/
|
||
|
||
|
||
/**
|
||
* new Ruler()
|
||
**/
|
||
function Ruler$3() {
|
||
// List of added rules. Each element is:
|
||
//
|
||
// {
|
||
// name: XXX,
|
||
// enabled: Boolean,
|
||
// fn: Function(),
|
||
// alt: [ name2, name3 ]
|
||
// }
|
||
//
|
||
this.__rules__ = [];
|
||
|
||
// Cached rule chains.
|
||
//
|
||
// First level - chain name, '' for default.
|
||
// Second level - diginal anchor for fast filtering by charcodes.
|
||
//
|
||
this.__cache__ = null;
|
||
}
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
// Helper methods, should not be used directly
|
||
|
||
|
||
// Find rule index by name
|
||
//
|
||
Ruler$3.prototype.__find__ = function (name) {
|
||
for (var i = 0; i < this.__rules__.length; i++) {
|
||
if (this.__rules__[i].name === name) {
|
||
return i;
|
||
}
|
||
}
|
||
return -1;
|
||
};
|
||
|
||
|
||
// Build rules lookup cache
|
||
//
|
||
Ruler$3.prototype.__compile__ = function () {
|
||
var self = this;
|
||
var chains = [ '' ];
|
||
|
||
// collect unique names
|
||
self.__rules__.forEach(function (rule) {
|
||
if (!rule.enabled) { return; }
|
||
|
||
rule.alt.forEach(function (altName) {
|
||
if (chains.indexOf(altName) < 0) {
|
||
chains.push(altName);
|
||
}
|
||
});
|
||
});
|
||
|
||
self.__cache__ = {};
|
||
|
||
chains.forEach(function (chain) {
|
||
self.__cache__[chain] = [];
|
||
self.__rules__.forEach(function (rule) {
|
||
if (!rule.enabled) { return; }
|
||
|
||
if (chain && rule.alt.indexOf(chain) < 0) { return; }
|
||
|
||
self.__cache__[chain].push(rule.fn);
|
||
});
|
||
});
|
||
};
|
||
|
||
|
||
/**
|
||
* Ruler.at(name, fn [, options])
|
||
* - name (String): rule name to replace.
|
||
* - fn (Function): new rule function.
|
||
* - options (Object): new rule options (not mandatory).
|
||
*
|
||
* Replace rule by name with new function & options. Throws error if name not
|
||
* found.
|
||
*
|
||
* ##### Options:
|
||
*
|
||
* - __alt__ - array with names of "alternate" chains.
|
||
*
|
||
* ##### Example
|
||
*
|
||
* Replace existing typographer replacement rule with new one:
|
||
*
|
||
* ```javascript
|
||
* var md = require('markdown-it')();
|
||
*
|
||
* md.core.ruler.at('replacements', function replace(state) {
|
||
* //...
|
||
* });
|
||
* ```
|
||
**/
|
||
Ruler$3.prototype.at = function (name, fn, options) {
|
||
var index = this.__find__(name);
|
||
var opt = options || {};
|
||
|
||
if (index === -1) { throw new Error('Parser rule not found: ' + name); }
|
||
|
||
this.__rules__[index].fn = fn;
|
||
this.__rules__[index].alt = opt.alt || [];
|
||
this.__cache__ = null;
|
||
};
|
||
|
||
|
||
/**
|
||
* Ruler.before(beforeName, ruleName, fn [, options])
|
||
* - beforeName (String): new rule will be added before this one.
|
||
* - ruleName (String): name of added rule.
|
||
* - fn (Function): rule function.
|
||
* - options (Object): rule options (not mandatory).
|
||
*
|
||
* Add new rule to chain before one with given name. See also
|
||
* [[Ruler.after]], [[Ruler.push]].
|
||
*
|
||
* ##### Options:
|
||
*
|
||
* - __alt__ - array with names of "alternate" chains.
|
||
*
|
||
* ##### Example
|
||
*
|
||
* ```javascript
|
||
* var md = require('markdown-it')();
|
||
*
|
||
* md.block.ruler.before('paragraph', 'my_rule', function replace(state) {
|
||
* //...
|
||
* });
|
||
* ```
|
||
**/
|
||
Ruler$3.prototype.before = function (beforeName, ruleName, fn, options) {
|
||
var index = this.__find__(beforeName);
|
||
var opt = options || {};
|
||
|
||
if (index === -1) { throw new Error('Parser rule not found: ' + beforeName); }
|
||
|
||
this.__rules__.splice(index, 0, {
|
||
name: ruleName,
|
||
enabled: true,
|
||
fn: fn,
|
||
alt: opt.alt || []
|
||
});
|
||
|
||
this.__cache__ = null;
|
||
};
|
||
|
||
|
||
/**
|
||
* Ruler.after(afterName, ruleName, fn [, options])
|
||
* - afterName (String): new rule will be added after this one.
|
||
* - ruleName (String): name of added rule.
|
||
* - fn (Function): rule function.
|
||
* - options (Object): rule options (not mandatory).
|
||
*
|
||
* Add new rule to chain after one with given name. See also
|
||
* [[Ruler.before]], [[Ruler.push]].
|
||
*
|
||
* ##### Options:
|
||
*
|
||
* - __alt__ - array with names of "alternate" chains.
|
||
*
|
||
* ##### Example
|
||
*
|
||
* ```javascript
|
||
* var md = require('markdown-it')();
|
||
*
|
||
* md.inline.ruler.after('text', 'my_rule', function replace(state) {
|
||
* //...
|
||
* });
|
||
* ```
|
||
**/
|
||
Ruler$3.prototype.after = function (afterName, ruleName, fn, options) {
|
||
var index = this.__find__(afterName);
|
||
var opt = options || {};
|
||
|
||
if (index === -1) { throw new Error('Parser rule not found: ' + afterName); }
|
||
|
||
this.__rules__.splice(index + 1, 0, {
|
||
name: ruleName,
|
||
enabled: true,
|
||
fn: fn,
|
||
alt: opt.alt || []
|
||
});
|
||
|
||
this.__cache__ = null;
|
||
};
|
||
|
||
/**
|
||
* Ruler.push(ruleName, fn [, options])
|
||
* - ruleName (String): name of added rule.
|
||
* - fn (Function): rule function.
|
||
* - options (Object): rule options (not mandatory).
|
||
*
|
||
* Push new rule to the end of chain. See also
|
||
* [[Ruler.before]], [[Ruler.after]].
|
||
*
|
||
* ##### Options:
|
||
*
|
||
* - __alt__ - array with names of "alternate" chains.
|
||
*
|
||
* ##### Example
|
||
*
|
||
* ```javascript
|
||
* var md = require('markdown-it')();
|
||
*
|
||
* md.core.ruler.push('my_rule', function replace(state) {
|
||
* //...
|
||
* });
|
||
* ```
|
||
**/
|
||
Ruler$3.prototype.push = function (ruleName, fn, options) {
|
||
var opt = options || {};
|
||
|
||
this.__rules__.push({
|
||
name: ruleName,
|
||
enabled: true,
|
||
fn: fn,
|
||
alt: opt.alt || []
|
||
});
|
||
|
||
this.__cache__ = null;
|
||
};
|
||
|
||
|
||
/**
|
||
* Ruler.enable(list [, ignoreInvalid]) -> Array
|
||
* - list (String|Array): list of rule names to enable.
|
||
* - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.
|
||
*
|
||
* Enable rules with given names. If any rule name not found - throw Error.
|
||
* Errors can be disabled by second param.
|
||
*
|
||
* Returns list of found rule names (if no exception happened).
|
||
*
|
||
* See also [[Ruler.disable]], [[Ruler.enableOnly]].
|
||
**/
|
||
Ruler$3.prototype.enable = function (list, ignoreInvalid) {
|
||
if (!Array.isArray(list)) { list = [ list ]; }
|
||
|
||
var result = [];
|
||
|
||
// Search by name and enable
|
||
list.forEach(function (name) {
|
||
var idx = this.__find__(name);
|
||
|
||
if (idx < 0) {
|
||
if (ignoreInvalid) { return; }
|
||
throw new Error('Rules manager: invalid rule name ' + name);
|
||
}
|
||
this.__rules__[idx].enabled = true;
|
||
result.push(name);
|
||
}, this);
|
||
|
||
this.__cache__ = null;
|
||
return result;
|
||
};
|
||
|
||
|
||
/**
|
||
* Ruler.enableOnly(list [, ignoreInvalid])
|
||
* - list (String|Array): list of rule names to enable (whitelist).
|
||
* - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.
|
||
*
|
||
* Enable rules with given names, and disable everything else. If any rule name
|
||
* not found - throw Error. Errors can be disabled by second param.
|
||
*
|
||
* See also [[Ruler.disable]], [[Ruler.enable]].
|
||
**/
|
||
Ruler$3.prototype.enableOnly = function (list, ignoreInvalid) {
|
||
if (!Array.isArray(list)) { list = [ list ]; }
|
||
|
||
this.__rules__.forEach(function (rule) { rule.enabled = false; });
|
||
|
||
this.enable(list, ignoreInvalid);
|
||
};
|
||
|
||
|
||
/**
|
||
* Ruler.disable(list [, ignoreInvalid]) -> Array
|
||
* - list (String|Array): list of rule names to disable.
|
||
* - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.
|
||
*
|
||
* Disable rules with given names. If any rule name not found - throw Error.
|
||
* Errors can be disabled by second param.
|
||
*
|
||
* Returns list of found rule names (if no exception happened).
|
||
*
|
||
* See also [[Ruler.enable]], [[Ruler.enableOnly]].
|
||
**/
|
||
Ruler$3.prototype.disable = function (list, ignoreInvalid) {
|
||
if (!Array.isArray(list)) { list = [ list ]; }
|
||
|
||
var result = [];
|
||
|
||
// Search by name and disable
|
||
list.forEach(function (name) {
|
||
var idx = this.__find__(name);
|
||
|
||
if (idx < 0) {
|
||
if (ignoreInvalid) { return; }
|
||
throw new Error('Rules manager: invalid rule name ' + name);
|
||
}
|
||
this.__rules__[idx].enabled = false;
|
||
result.push(name);
|
||
}, this);
|
||
|
||
this.__cache__ = null;
|
||
return result;
|
||
};
|
||
|
||
|
||
/**
|
||
* Ruler.getRules(chainName) -> Array
|
||
*
|
||
* Return array of active functions (rules) for given chain name. It analyzes
|
||
* rules configuration, compiles caches if not exists and returns result.
|
||
*
|
||
* Default chain name is `''` (empty string). It can't be skipped. That's
|
||
* done intentionally, to keep signature monomorphic for high speed.
|
||
**/
|
||
Ruler$3.prototype.getRules = function (chainName) {
|
||
if (this.__cache__ === null) {
|
||
this.__compile__();
|
||
}
|
||
|
||
// Chain can be empty, if rules disabled. But we still have to return Array.
|
||
return this.__cache__[chainName] || [];
|
||
};
|
||
|
||
var ruler = Ruler$3;
|
||
|
||
// https://spec.commonmark.org/0.29/#line-ending
|
||
var NEWLINES_RE = /\r\n?|\n/g;
|
||
var NULL_RE = /\0/g;
|
||
|
||
|
||
var normalize = function normalize(state) {
|
||
var str;
|
||
|
||
// Normalize newlines
|
||
str = state.src.replace(NEWLINES_RE, '\n');
|
||
|
||
// Replace NULL characters
|
||
str = str.replace(NULL_RE, '\uFFFD');
|
||
|
||
state.src = str;
|
||
};
|
||
|
||
var block = function block(state) {
|
||
var token;
|
||
|
||
if (state.inlineMode) {
|
||
token = new state.Token('inline', '', 0);
|
||
token.content = state.src;
|
||
token.map = [ 0, 1 ];
|
||
token.children = [];
|
||
state.tokens.push(token);
|
||
} else {
|
||
state.md.block.parse(state.src, state.md, state.env, state.tokens);
|
||
}
|
||
};
|
||
|
||
var inline = function inline(state) {
|
||
var tokens = state.tokens, tok, i, l;
|
||
|
||
// Parse inlines
|
||
for (i = 0, l = tokens.length; i < l; i++) {
|
||
tok = tokens[i];
|
||
if (tok.type === 'inline') {
|
||
state.md.inline.parse(tok.content, state.md, state.env, tok.children);
|
||
}
|
||
}
|
||
};
|
||
|
||
var arrayReplaceAt = utils$1.arrayReplaceAt;
|
||
|
||
|
||
function isLinkOpen(str) {
|
||
return /^<a[>\s]/i.test(str);
|
||
}
|
||
function isLinkClose(str) {
|
||
return /^<\/a\s*>/i.test(str);
|
||
}
|
||
|
||
|
||
var linkify = function linkify(state) {
|
||
var i, j, l, tokens, token, currentToken, nodes, ln, text, pos, lastPos,
|
||
level, htmlLinkLevel, url, fullUrl, urlText,
|
||
blockTokens = state.tokens,
|
||
links;
|
||
|
||
if (!state.md.options.linkify) { return; }
|
||
|
||
for (j = 0, l = blockTokens.length; j < l; j++) {
|
||
if (blockTokens[j].type !== 'inline' ||
|
||
!state.md.linkify.pretest(blockTokens[j].content)) {
|
||
continue;
|
||
}
|
||
|
||
tokens = blockTokens[j].children;
|
||
|
||
htmlLinkLevel = 0;
|
||
|
||
// We scan from the end, to keep position when new tags added.
|
||
// Use reversed logic in links start/end match
|
||
for (i = tokens.length - 1; i >= 0; i--) {
|
||
currentToken = tokens[i];
|
||
|
||
// Skip content of markdown links
|
||
if (currentToken.type === 'link_close') {
|
||
i--;
|
||
while (tokens[i].level !== currentToken.level && tokens[i].type !== 'link_open') {
|
||
i--;
|
||
}
|
||
continue;
|
||
}
|
||
|
||
// Skip content of html tag links
|
||
if (currentToken.type === 'html_inline') {
|
||
if (isLinkOpen(currentToken.content) && htmlLinkLevel > 0) {
|
||
htmlLinkLevel--;
|
||
}
|
||
if (isLinkClose(currentToken.content)) {
|
||
htmlLinkLevel++;
|
||
}
|
||
}
|
||
if (htmlLinkLevel > 0) { continue; }
|
||
|
||
if (currentToken.type === 'text' && state.md.linkify.test(currentToken.content)) {
|
||
|
||
text = currentToken.content;
|
||
links = state.md.linkify.match(text);
|
||
|
||
// Now split string to nodes
|
||
nodes = [];
|
||
level = currentToken.level;
|
||
lastPos = 0;
|
||
|
||
for (ln = 0; ln < links.length; ln++) {
|
||
|
||
url = links[ln].url;
|
||
fullUrl = state.md.normalizeLink(url);
|
||
if (!state.md.validateLink(fullUrl)) { continue; }
|
||
|
||
urlText = links[ln].text;
|
||
|
||
// Linkifier might send raw hostnames like "example.com", where url
|
||
// starts with domain name. So we prepend http:// in those cases,
|
||
// and remove it afterwards.
|
||
//
|
||
if (!links[ln].schema) {
|
||
urlText = state.md.normalizeLinkText('http://' + urlText).replace(/^http:\/\//, '');
|
||
} else if (links[ln].schema === 'mailto:' && !/^mailto:/i.test(urlText)) {
|
||
urlText = state.md.normalizeLinkText('mailto:' + urlText).replace(/^mailto:/, '');
|
||
} else {
|
||
urlText = state.md.normalizeLinkText(urlText);
|
||
}
|
||
|
||
pos = links[ln].index;
|
||
|
||
if (pos > lastPos) {
|
||
token = new state.Token('text', '', 0);
|
||
token.content = text.slice(lastPos, pos);
|
||
token.level = level;
|
||
nodes.push(token);
|
||
}
|
||
|
||
token = new state.Token('link_open', 'a', 1);
|
||
token.attrs = [ [ 'href', fullUrl ] ];
|
||
token.level = level++;
|
||
token.markup = 'linkify';
|
||
token.info = 'auto';
|
||
nodes.push(token);
|
||
|
||
token = new state.Token('text', '', 0);
|
||
token.content = urlText;
|
||
token.level = level;
|
||
nodes.push(token);
|
||
|
||
token = new state.Token('link_close', 'a', -1);
|
||
token.level = --level;
|
||
token.markup = 'linkify';
|
||
token.info = 'auto';
|
||
nodes.push(token);
|
||
|
||
lastPos = links[ln].lastIndex;
|
||
}
|
||
if (lastPos < text.length) {
|
||
token = new state.Token('text', '', 0);
|
||
token.content = text.slice(lastPos);
|
||
token.level = level;
|
||
nodes.push(token);
|
||
}
|
||
|
||
// replace current node
|
||
blockTokens[j].children = tokens = arrayReplaceAt(tokens, i, nodes);
|
||
}
|
||
}
|
||
}
|
||
};
|
||
|
||
// TODO:
|
||
// - fractionals 1/2, 1/4, 3/4 -> ½, ¼, ¾
|
||
// - miltiplication 2 x 4 -> 2 × 4
|
||
|
||
var RARE_RE = /\+-|\.\.|\?\?\?\?|!!!!|,,|--/;
|
||
|
||
// Workaround for phantomjs - need regex without /g flag,
|
||
// or root check will fail every second time
|
||
var SCOPED_ABBR_TEST_RE = /\((c|tm|r|p)\)/i;
|
||
|
||
var SCOPED_ABBR_RE = /\((c|tm|r|p)\)/ig;
|
||
var SCOPED_ABBR = {
|
||
c: '©',
|
||
r: '®',
|
||
p: '§',
|
||
tm: '™'
|
||
};
|
||
|
||
function replaceFn(match, name) {
|
||
return SCOPED_ABBR[name.toLowerCase()];
|
||
}
|
||
|
||
function replace_scoped(inlineTokens) {
|
||
var i, token, inside_autolink = 0;
|
||
|
||
for (i = inlineTokens.length - 1; i >= 0; i--) {
|
||
token = inlineTokens[i];
|
||
|
||
if (token.type === 'text' && !inside_autolink) {
|
||
token.content = token.content.replace(SCOPED_ABBR_RE, replaceFn);
|
||
}
|
||
|
||
if (token.type === 'link_open' && token.info === 'auto') {
|
||
inside_autolink--;
|
||
}
|
||
|
||
if (token.type === 'link_close' && token.info === 'auto') {
|
||
inside_autolink++;
|
||
}
|
||
}
|
||
}
|
||
|
||
function replace_rare(inlineTokens) {
|
||
var i, token, inside_autolink = 0;
|
||
|
||
for (i = inlineTokens.length - 1; i >= 0; i--) {
|
||
token = inlineTokens[i];
|
||
|
||
if (token.type === 'text' && !inside_autolink) {
|
||
if (RARE_RE.test(token.content)) {
|
||
token.content = token.content
|
||
.replace(/\+-/g, '±')
|
||
// .., ..., ....... -> …
|
||
// but ?..... & !..... -> ?.. & !..
|
||
.replace(/\.{2,}/g, '…').replace(/([?!])…/g, '$1..')
|
||
.replace(/([?!]){4,}/g, '$1$1$1').replace(/,{2,}/g, ',')
|
||
// em-dash
|
||
.replace(/(^|[^-])---(?=[^-]|$)/mg, '$1\u2014')
|
||
// en-dash
|
||
.replace(/(^|\s)--(?=\s|$)/mg, '$1\u2013')
|
||
.replace(/(^|[^-\s])--(?=[^-\s]|$)/mg, '$1\u2013');
|
||
}
|
||
}
|
||
|
||
if (token.type === 'link_open' && token.info === 'auto') {
|
||
inside_autolink--;
|
||
}
|
||
|
||
if (token.type === 'link_close' && token.info === 'auto') {
|
||
inside_autolink++;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
var replacements = function replace(state) {
|
||
var blkIdx;
|
||
|
||
if (!state.md.options.typographer) { return; }
|
||
|
||
for (blkIdx = state.tokens.length - 1; blkIdx >= 0; blkIdx--) {
|
||
|
||
if (state.tokens[blkIdx].type !== 'inline') { continue; }
|
||
|
||
if (SCOPED_ABBR_TEST_RE.test(state.tokens[blkIdx].content)) {
|
||
replace_scoped(state.tokens[blkIdx].children);
|
||
}
|
||
|
||
if (RARE_RE.test(state.tokens[blkIdx].content)) {
|
||
replace_rare(state.tokens[blkIdx].children);
|
||
}
|
||
|
||
}
|
||
};
|
||
|
||
var isWhiteSpace$1 = utils$1.isWhiteSpace;
|
||
var isPunctChar$1 = utils$1.isPunctChar;
|
||
var isMdAsciiPunct$1 = utils$1.isMdAsciiPunct;
|
||
|
||
var QUOTE_TEST_RE = /['"]/;
|
||
var QUOTE_RE = /['"]/g;
|
||
var APOSTROPHE = '\u2019'; /* ’ */
|
||
|
||
|
||
function replaceAt(str, index, ch) {
|
||
return str.substr(0, index) + ch + str.substr(index + 1);
|
||
}
|
||
|
||
function process_inlines(tokens, state) {
|
||
var i, token, text, t, pos, max, thisLevel, item, lastChar, nextChar,
|
||
isLastPunctChar, isNextPunctChar, isLastWhiteSpace, isNextWhiteSpace,
|
||
canOpen, canClose, j, isSingle, stack, openQuote, closeQuote;
|
||
|
||
stack = [];
|
||
|
||
for (i = 0; i < tokens.length; i++) {
|
||
token = tokens[i];
|
||
|
||
thisLevel = tokens[i].level;
|
||
|
||
for (j = stack.length - 1; j >= 0; j--) {
|
||
if (stack[j].level <= thisLevel) { break; }
|
||
}
|
||
stack.length = j + 1;
|
||
|
||
if (token.type !== 'text') { continue; }
|
||
|
||
text = token.content;
|
||
pos = 0;
|
||
max = text.length;
|
||
|
||
/*eslint no-labels:0,block-scoped-var:0*/
|
||
OUTER:
|
||
while (pos < max) {
|
||
QUOTE_RE.lastIndex = pos;
|
||
t = QUOTE_RE.exec(text);
|
||
if (!t) { break; }
|
||
|
||
canOpen = canClose = true;
|
||
pos = t.index + 1;
|
||
isSingle = (t[0] === "'");
|
||
|
||
// Find previous character,
|
||
// default to space if it's the beginning of the line
|
||
//
|
||
lastChar = 0x20;
|
||
|
||
if (t.index - 1 >= 0) {
|
||
lastChar = text.charCodeAt(t.index - 1);
|
||
} else {
|
||
for (j = i - 1; j >= 0; j--) {
|
||
if (tokens[j].type === 'softbreak' || tokens[j].type === 'hardbreak') break; // lastChar defaults to 0x20
|
||
if (!tokens[j].content) continue; // should skip all tokens except 'text', 'html_inline' or 'code_inline'
|
||
|
||
lastChar = tokens[j].content.charCodeAt(tokens[j].content.length - 1);
|
||
break;
|
||
}
|
||
}
|
||
|
||
// Find next character,
|
||
// default to space if it's the end of the line
|
||
//
|
||
nextChar = 0x20;
|
||
|
||
if (pos < max) {
|
||
nextChar = text.charCodeAt(pos);
|
||
} else {
|
||
for (j = i + 1; j < tokens.length; j++) {
|
||
if (tokens[j].type === 'softbreak' || tokens[j].type === 'hardbreak') break; // nextChar defaults to 0x20
|
||
if (!tokens[j].content) continue; // should skip all tokens except 'text', 'html_inline' or 'code_inline'
|
||
|
||
nextChar = tokens[j].content.charCodeAt(0);
|
||
break;
|
||
}
|
||
}
|
||
|
||
isLastPunctChar = isMdAsciiPunct$1(lastChar) || isPunctChar$1(String.fromCharCode(lastChar));
|
||
isNextPunctChar = isMdAsciiPunct$1(nextChar) || isPunctChar$1(String.fromCharCode(nextChar));
|
||
|
||
isLastWhiteSpace = isWhiteSpace$1(lastChar);
|
||
isNextWhiteSpace = isWhiteSpace$1(nextChar);
|
||
|
||
if (isNextWhiteSpace) {
|
||
canOpen = false;
|
||
} else if (isNextPunctChar) {
|
||
if (!(isLastWhiteSpace || isLastPunctChar)) {
|
||
canOpen = false;
|
||
}
|
||
}
|
||
|
||
if (isLastWhiteSpace) {
|
||
canClose = false;
|
||
} else if (isLastPunctChar) {
|
||
if (!(isNextWhiteSpace || isNextPunctChar)) {
|
||
canClose = false;
|
||
}
|
||
}
|
||
|
||
if (nextChar === 0x22 /* " */ && t[0] === '"') {
|
||
if (lastChar >= 0x30 /* 0 */ && lastChar <= 0x39 /* 9 */) {
|
||
// special case: 1"" - count first quote as an inch
|
||
canClose = canOpen = false;
|
||
}
|
||
}
|
||
|
||
if (canOpen && canClose) {
|
||
// Replace quotes in the middle of punctuation sequence, but not
|
||
// in the middle of the words, i.e.:
|
||
//
|
||
// 1. foo " bar " baz - not replaced
|
||
// 2. foo-"-bar-"-baz - replaced
|
||
// 3. foo"bar"baz - not replaced
|
||
//
|
||
canOpen = isLastPunctChar;
|
||
canClose = isNextPunctChar;
|
||
}
|
||
|
||
if (!canOpen && !canClose) {
|
||
// middle of word
|
||
if (isSingle) {
|
||
token.content = replaceAt(token.content, t.index, APOSTROPHE);
|
||
}
|
||
continue;
|
||
}
|
||
|
||
if (canClose) {
|
||
// this could be a closing quote, rewind the stack to get a match
|
||
for (j = stack.length - 1; j >= 0; j--) {
|
||
item = stack[j];
|
||
if (stack[j].level < thisLevel) { break; }
|
||
if (item.single === isSingle && stack[j].level === thisLevel) {
|
||
item = stack[j];
|
||
|
||
if (isSingle) {
|
||
openQuote = state.md.options.quotes[2];
|
||
closeQuote = state.md.options.quotes[3];
|
||
} else {
|
||
openQuote = state.md.options.quotes[0];
|
||
closeQuote = state.md.options.quotes[1];
|
||
}
|
||
|
||
// replace token.content *before* tokens[item.token].content,
|
||
// because, if they are pointing at the same token, replaceAt
|
||
// could mess up indices when quote length != 1
|
||
token.content = replaceAt(token.content, t.index, closeQuote);
|
||
tokens[item.token].content = replaceAt(
|
||
tokens[item.token].content, item.pos, openQuote);
|
||
|
||
pos += closeQuote.length - 1;
|
||
if (item.token === i) { pos += openQuote.length - 1; }
|
||
|
||
text = token.content;
|
||
max = text.length;
|
||
|
||
stack.length = j;
|
||
continue OUTER;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (canOpen) {
|
||
stack.push({
|
||
token: i,
|
||
pos: t.index,
|
||
single: isSingle,
|
||
level: thisLevel
|
||
});
|
||
} else if (canClose && isSingle) {
|
||
token.content = replaceAt(token.content, t.index, APOSTROPHE);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
var smartquotes = function smartquotes(state) {
|
||
/*eslint max-depth:0*/
|
||
var blkIdx;
|
||
|
||
if (!state.md.options.typographer) { return; }
|
||
|
||
for (blkIdx = state.tokens.length - 1; blkIdx >= 0; blkIdx--) {
|
||
|
||
if (state.tokens[blkIdx].type !== 'inline' ||
|
||
!QUOTE_TEST_RE.test(state.tokens[blkIdx].content)) {
|
||
continue;
|
||
}
|
||
|
||
process_inlines(state.tokens[blkIdx].children, state);
|
||
}
|
||
};
|
||
|
||
/**
|
||
* class Token
|
||
**/
|
||
|
||
/**
|
||
* new Token(type, tag, nesting)
|
||
*
|
||
* Create new token and fill passed properties.
|
||
**/
|
||
function Token$3(type, tag, nesting) {
|
||
/**
|
||
* Token#type -> String
|
||
*
|
||
* Type of the token (string, e.g. "paragraph_open")
|
||
**/
|
||
this.type = type;
|
||
|
||
/**
|
||
* Token#tag -> String
|
||
*
|
||
* html tag name, e.g. "p"
|
||
**/
|
||
this.tag = tag;
|
||
|
||
/**
|
||
* Token#attrs -> Array
|
||
*
|
||
* Html attributes. Format: `[ [ name1, value1 ], [ name2, value2 ] ]`
|
||
**/
|
||
this.attrs = null;
|
||
|
||
/**
|
||
* Token#map -> Array
|
||
*
|
||
* Source map info. Format: `[ line_begin, line_end ]`
|
||
**/
|
||
this.map = null;
|
||
|
||
/**
|
||
* Token#nesting -> Number
|
||
*
|
||
* Level change (number in {-1, 0, 1} set), where:
|
||
*
|
||
* - `1` means the tag is opening
|
||
* - `0` means the tag is self-closing
|
||
* - `-1` means the tag is closing
|
||
**/
|
||
this.nesting = nesting;
|
||
|
||
/**
|
||
* Token#level -> Number
|
||
*
|
||
* nesting level, the same as `state.level`
|
||
**/
|
||
this.level = 0;
|
||
|
||
/**
|
||
* Token#children -> Array
|
||
*
|
||
* An array of child nodes (inline and img tokens)
|
||
**/
|
||
this.children = null;
|
||
|
||
/**
|
||
* Token#content -> String
|
||
*
|
||
* In a case of self-closing tag (code, html, fence, etc.),
|
||
* it has contents of this tag.
|
||
**/
|
||
this.content = '';
|
||
|
||
/**
|
||
* Token#markup -> String
|
||
*
|
||
* '*' or '_' for emphasis, fence string for fence, etc.
|
||
**/
|
||
this.markup = '';
|
||
|
||
/**
|
||
* Token#info -> String
|
||
*
|
||
* Additional information:
|
||
*
|
||
* - Info string for "fence" tokens
|
||
* - The value "auto" for autolink "link_open" and "link_close" tokens
|
||
* - The string value of the item marker for ordered-list "list_item_open" tokens
|
||
**/
|
||
this.info = '';
|
||
|
||
/**
|
||
* Token#meta -> Object
|
||
*
|
||
* A place for plugins to store an arbitrary data
|
||
**/
|
||
this.meta = null;
|
||
|
||
/**
|
||
* Token#block -> Boolean
|
||
*
|
||
* True for block-level tokens, false for inline tokens.
|
||
* Used in renderer to calculate line breaks
|
||
**/
|
||
this.block = false;
|
||
|
||
/**
|
||
* Token#hidden -> Boolean
|
||
*
|
||
* If it's true, ignore this element when rendering. Used for tight lists
|
||
* to hide paragraphs.
|
||
**/
|
||
this.hidden = false;
|
||
}
|
||
|
||
|
||
/**
|
||
* Token.attrIndex(name) -> Number
|
||
*
|
||
* Search attribute index by name.
|
||
**/
|
||
Token$3.prototype.attrIndex = function attrIndex(name) {
|
||
var attrs, i, len;
|
||
|
||
if (!this.attrs) { return -1; }
|
||
|
||
attrs = this.attrs;
|
||
|
||
for (i = 0, len = attrs.length; i < len; i++) {
|
||
if (attrs[i][0] === name) { return i; }
|
||
}
|
||
return -1;
|
||
};
|
||
|
||
|
||
/**
|
||
* Token.attrPush(attrData)
|
||
*
|
||
* Add `[ name, value ]` attribute to list. Init attrs if necessary
|
||
**/
|
||
Token$3.prototype.attrPush = function attrPush(attrData) {
|
||
if (this.attrs) {
|
||
this.attrs.push(attrData);
|
||
} else {
|
||
this.attrs = [ attrData ];
|
||
}
|
||
};
|
||
|
||
|
||
/**
|
||
* Token.attrSet(name, value)
|
||
*
|
||
* Set `name` attribute to `value`. Override old value if exists.
|
||
**/
|
||
Token$3.prototype.attrSet = function attrSet(name, value) {
|
||
var idx = this.attrIndex(name),
|
||
attrData = [ name, value ];
|
||
|
||
if (idx < 0) {
|
||
this.attrPush(attrData);
|
||
} else {
|
||
this.attrs[idx] = attrData;
|
||
}
|
||
};
|
||
|
||
|
||
/**
|
||
* Token.attrGet(name)
|
||
*
|
||
* Get the value of attribute `name`, or null if it does not exist.
|
||
**/
|
||
Token$3.prototype.attrGet = function attrGet(name) {
|
||
var idx = this.attrIndex(name), value = null;
|
||
if (idx >= 0) {
|
||
value = this.attrs[idx][1];
|
||
}
|
||
return value;
|
||
};
|
||
|
||
|
||
/**
|
||
* Token.attrJoin(name, value)
|
||
*
|
||
* Join value to existing attribute via space. Or create new attribute if not
|
||
* exists. Useful to operate with token classes.
|
||
**/
|
||
Token$3.prototype.attrJoin = function attrJoin(name, value) {
|
||
var idx = this.attrIndex(name);
|
||
|
||
if (idx < 0) {
|
||
this.attrPush([ name, value ]);
|
||
} else {
|
||
this.attrs[idx][1] = this.attrs[idx][1] + ' ' + value;
|
||
}
|
||
};
|
||
|
||
|
||
var token = Token$3;
|
||
|
||
var Token$2 = token;
|
||
|
||
|
||
function StateCore(src, md, env) {
|
||
this.src = src;
|
||
this.env = env;
|
||
this.tokens = [];
|
||
this.inlineMode = false;
|
||
this.md = md; // link to parser instance
|
||
}
|
||
|
||
// re-export Token class to use in core rules
|
||
StateCore.prototype.Token = Token$2;
|
||
|
||
|
||
var state_core = StateCore;
|
||
|
||
/** internal
|
||
* class Core
|
||
*
|
||
* Top-level rules executor. Glues block/inline parsers and does intermediate
|
||
* transformations.
|
||
**/
|
||
|
||
|
||
var Ruler$2 = ruler;
|
||
|
||
|
||
var _rules$2 = [
|
||
[ 'normalize', normalize ],
|
||
[ 'block', block ],
|
||
[ 'inline', inline ],
|
||
[ 'linkify', linkify ],
|
||
[ 'replacements', replacements ],
|
||
[ 'smartquotes', smartquotes ]
|
||
];
|
||
|
||
|
||
/**
|
||
* new Core()
|
||
**/
|
||
function Core() {
|
||
/**
|
||
* Core#ruler -> Ruler
|
||
*
|
||
* [[Ruler]] instance. Keep configuration of core rules.
|
||
**/
|
||
this.ruler = new Ruler$2();
|
||
|
||
for (var i = 0; i < _rules$2.length; i++) {
|
||
this.ruler.push(_rules$2[i][0], _rules$2[i][1]);
|
||
}
|
||
}
|
||
|
||
|
||
/**
|
||
* Core.process(state)
|
||
*
|
||
* Executes core chain rules.
|
||
**/
|
||
Core.prototype.process = function (state) {
|
||
var i, l, rules;
|
||
|
||
rules = this.ruler.getRules('');
|
||
|
||
for (i = 0, l = rules.length; i < l; i++) {
|
||
rules[i](state);
|
||
}
|
||
};
|
||
|
||
Core.prototype.State = state_core;
|
||
|
||
|
||
var parser_core = Core;
|
||
|
||
var isSpace$a = utils$1.isSpace;
|
||
|
||
|
||
function getLine(state, line) {
|
||
var pos = state.bMarks[line] + state.tShift[line],
|
||
max = state.eMarks[line];
|
||
|
||
return state.src.substr(pos, max - pos);
|
||
}
|
||
|
||
function escapedSplit(str) {
|
||
var result = [],
|
||
pos = 0,
|
||
max = str.length,
|
||
ch,
|
||
isEscaped = false,
|
||
lastPos = 0,
|
||
current = '';
|
||
|
||
ch = str.charCodeAt(pos);
|
||
|
||
while (pos < max) {
|
||
if (ch === 0x7c/* | */) {
|
||
if (!isEscaped) {
|
||
// pipe separating cells, '|'
|
||
result.push(current + str.substring(lastPos, pos));
|
||
current = '';
|
||
lastPos = pos + 1;
|
||
} else {
|
||
// escaped pipe, '\|'
|
||
current += str.substring(lastPos, pos - 1);
|
||
lastPos = pos;
|
||
}
|
||
}
|
||
|
||
isEscaped = (ch === 0x5c/* \ */);
|
||
pos++;
|
||
|
||
ch = str.charCodeAt(pos);
|
||
}
|
||
|
||
result.push(current + str.substring(lastPos));
|
||
|
||
return result;
|
||
}
|
||
|
||
|
||
var table = function table(state, startLine, endLine, silent) {
|
||
var ch, lineText, pos, i, l, nextLine, columns, columnCount, token,
|
||
aligns, t, tableLines, tbodyLines, oldParentType, terminate,
|
||
terminatorRules, firstCh, secondCh;
|
||
|
||
// should have at least two lines
|
||
if (startLine + 2 > endLine) { return false; }
|
||
|
||
nextLine = startLine + 1;
|
||
|
||
if (state.sCount[nextLine] < state.blkIndent) { return false; }
|
||
|
||
// if it's indented more than 3 spaces, it should be a code block
|
||
if (state.sCount[nextLine] - state.blkIndent >= 4) { return false; }
|
||
|
||
// first character of the second line should be '|', '-', ':',
|
||
// and no other characters are allowed but spaces;
|
||
// basically, this is the equivalent of /^[-:|][-:|\s]*$/ regexp
|
||
|
||
pos = state.bMarks[nextLine] + state.tShift[nextLine];
|
||
if (pos >= state.eMarks[nextLine]) { return false; }
|
||
|
||
firstCh = state.src.charCodeAt(pos++);
|
||
if (firstCh !== 0x7C/* | */ && firstCh !== 0x2D/* - */ && firstCh !== 0x3A/* : */) { return false; }
|
||
|
||
if (pos >= state.eMarks[nextLine]) { return false; }
|
||
|
||
secondCh = state.src.charCodeAt(pos++);
|
||
if (secondCh !== 0x7C/* | */ && secondCh !== 0x2D/* - */ && secondCh !== 0x3A/* : */ && !isSpace$a(secondCh)) {
|
||
return false;
|
||
}
|
||
|
||
// if first character is '-', then second character must not be a space
|
||
// (due to parsing ambiguity with list)
|
||
if (firstCh === 0x2D/* - */ && isSpace$a(secondCh)) { return false; }
|
||
|
||
while (pos < state.eMarks[nextLine]) {
|
||
ch = state.src.charCodeAt(pos);
|
||
|
||
if (ch !== 0x7C/* | */ && ch !== 0x2D/* - */ && ch !== 0x3A/* : */ && !isSpace$a(ch)) { return false; }
|
||
|
||
pos++;
|
||
}
|
||
|
||
lineText = getLine(state, startLine + 1);
|
||
|
||
columns = lineText.split('|');
|
||
aligns = [];
|
||
for (i = 0; i < columns.length; i++) {
|
||
t = columns[i].trim();
|
||
if (!t) {
|
||
// allow empty columns before and after table, but not in between columns;
|
||
// e.g. allow ` |---| `, disallow ` ---||--- `
|
||
if (i === 0 || i === columns.length - 1) {
|
||
continue;
|
||
} else {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
if (!/^:?-+:?$/.test(t)) { return false; }
|
||
if (t.charCodeAt(t.length - 1) === 0x3A/* : */) {
|
||
aligns.push(t.charCodeAt(0) === 0x3A/* : */ ? 'center' : 'right');
|
||
} else if (t.charCodeAt(0) === 0x3A/* : */) {
|
||
aligns.push('left');
|
||
} else {
|
||
aligns.push('');
|
||
}
|
||
}
|
||
|
||
lineText = getLine(state, startLine).trim();
|
||
if (lineText.indexOf('|') === -1) { return false; }
|
||
if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }
|
||
columns = escapedSplit(lineText);
|
||
if (columns.length && columns[0] === '') columns.shift();
|
||
if (columns.length && columns[columns.length - 1] === '') columns.pop();
|
||
|
||
// header row will define an amount of columns in the entire table,
|
||
// and align row should be exactly the same (the rest of the rows can differ)
|
||
columnCount = columns.length;
|
||
if (columnCount === 0 || columnCount !== aligns.length) { return false; }
|
||
|
||
if (silent) { return true; }
|
||
|
||
oldParentType = state.parentType;
|
||
state.parentType = 'table';
|
||
|
||
// use 'blockquote' lists for termination because it's
|
||
// the most similar to tables
|
||
terminatorRules = state.md.block.ruler.getRules('blockquote');
|
||
|
||
token = state.push('table_open', 'table', 1);
|
||
token.map = tableLines = [ startLine, 0 ];
|
||
|
||
token = state.push('thead_open', 'thead', 1);
|
||
token.map = [ startLine, startLine + 1 ];
|
||
|
||
token = state.push('tr_open', 'tr', 1);
|
||
token.map = [ startLine, startLine + 1 ];
|
||
|
||
for (i = 0; i < columns.length; i++) {
|
||
token = state.push('th_open', 'th', 1);
|
||
if (aligns[i]) {
|
||
token.attrs = [ [ 'style', 'text-align:' + aligns[i] ] ];
|
||
}
|
||
|
||
token = state.push('inline', '', 0);
|
||
token.content = columns[i].trim();
|
||
token.children = [];
|
||
|
||
token = state.push('th_close', 'th', -1);
|
||
}
|
||
|
||
token = state.push('tr_close', 'tr', -1);
|
||
token = state.push('thead_close', 'thead', -1);
|
||
|
||
for (nextLine = startLine + 2; nextLine < endLine; nextLine++) {
|
||
if (state.sCount[nextLine] < state.blkIndent) { break; }
|
||
|
||
terminate = false;
|
||
for (i = 0, l = terminatorRules.length; i < l; i++) {
|
||
if (terminatorRules[i](state, nextLine, endLine, true)) {
|
||
terminate = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (terminate) { break; }
|
||
lineText = getLine(state, nextLine).trim();
|
||
if (!lineText) { break; }
|
||
if (state.sCount[nextLine] - state.blkIndent >= 4) { break; }
|
||
columns = escapedSplit(lineText);
|
||
if (columns.length && columns[0] === '') columns.shift();
|
||
if (columns.length && columns[columns.length - 1] === '') columns.pop();
|
||
|
||
if (nextLine === startLine + 2) {
|
||
token = state.push('tbody_open', 'tbody', 1);
|
||
token.map = tbodyLines = [ startLine + 2, 0 ];
|
||
}
|
||
|
||
token = state.push('tr_open', 'tr', 1);
|
||
token.map = [ nextLine, nextLine + 1 ];
|
||
|
||
for (i = 0; i < columnCount; i++) {
|
||
token = state.push('td_open', 'td', 1);
|
||
if (aligns[i]) {
|
||
token.attrs = [ [ 'style', 'text-align:' + aligns[i] ] ];
|
||
}
|
||
|
||
token = state.push('inline', '', 0);
|
||
token.content = columns[i] ? columns[i].trim() : '';
|
||
token.children = [];
|
||
|
||
token = state.push('td_close', 'td', -1);
|
||
}
|
||
token = state.push('tr_close', 'tr', -1);
|
||
}
|
||
|
||
if (tbodyLines) {
|
||
token = state.push('tbody_close', 'tbody', -1);
|
||
tbodyLines[1] = nextLine;
|
||
}
|
||
|
||
token = state.push('table_close', 'table', -1);
|
||
tableLines[1] = nextLine;
|
||
|
||
state.parentType = oldParentType;
|
||
state.line = nextLine;
|
||
return true;
|
||
};
|
||
|
||
var code = function code(state, startLine, endLine/*, silent*/) {
|
||
var nextLine, last, token;
|
||
|
||
if (state.sCount[startLine] - state.blkIndent < 4) { return false; }
|
||
|
||
last = nextLine = startLine + 1;
|
||
|
||
while (nextLine < endLine) {
|
||
if (state.isEmpty(nextLine)) {
|
||
nextLine++;
|
||
continue;
|
||
}
|
||
|
||
if (state.sCount[nextLine] - state.blkIndent >= 4) {
|
||
nextLine++;
|
||
last = nextLine;
|
||
continue;
|
||
}
|
||
break;
|
||
}
|
||
|
||
state.line = last;
|
||
|
||
token = state.push('code_block', 'code', 0);
|
||
token.content = state.getLines(startLine, last, 4 + state.blkIndent, false) + '\n';
|
||
token.map = [ startLine, state.line ];
|
||
|
||
return true;
|
||
};
|
||
|
||
var fence = function fence(state, startLine, endLine, silent) {
|
||
var marker, len, params, nextLine, mem, token, markup,
|
||
haveEndMarker = false,
|
||
pos = state.bMarks[startLine] + state.tShift[startLine],
|
||
max = state.eMarks[startLine];
|
||
|
||
// if it's indented more than 3 spaces, it should be a code block
|
||
if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }
|
||
|
||
if (pos + 3 > max) { return false; }
|
||
|
||
marker = state.src.charCodeAt(pos);
|
||
|
||
if (marker !== 0x7E/* ~ */ && marker !== 0x60 /* ` */) {
|
||
return false;
|
||
}
|
||
|
||
// scan marker length
|
||
mem = pos;
|
||
pos = state.skipChars(pos, marker);
|
||
|
||
len = pos - mem;
|
||
|
||
if (len < 3) { return false; }
|
||
|
||
markup = state.src.slice(mem, pos);
|
||
params = state.src.slice(pos, max);
|
||
|
||
if (marker === 0x60 /* ` */) {
|
||
if (params.indexOf(String.fromCharCode(marker)) >= 0) {
|
||
return false;
|
||
}
|
||
}
|
||
|
||
// Since start is found, we can report success here in validation mode
|
||
if (silent) { return true; }
|
||
|
||
// search end of block
|
||
nextLine = startLine;
|
||
|
||
for (;;) {
|
||
nextLine++;
|
||
if (nextLine >= endLine) {
|
||
// unclosed block should be autoclosed by end of document.
|
||
// also block seems to be autoclosed by end of parent
|
||
break;
|
||
}
|
||
|
||
pos = mem = state.bMarks[nextLine] + state.tShift[nextLine];
|
||
max = state.eMarks[nextLine];
|
||
|
||
if (pos < max && state.sCount[nextLine] < state.blkIndent) {
|
||
// non-empty line with negative indent should stop the list:
|
||
// - ```
|
||
// test
|
||
break;
|
||
}
|
||
|
||
if (state.src.charCodeAt(pos) !== marker) { continue; }
|
||
|
||
if (state.sCount[nextLine] - state.blkIndent >= 4) {
|
||
// closing fence should be indented less than 4 spaces
|
||
continue;
|
||
}
|
||
|
||
pos = state.skipChars(pos, marker);
|
||
|
||
// closing code fence must be at least as long as the opening one
|
||
if (pos - mem < len) { continue; }
|
||
|
||
// make sure tail has spaces only
|
||
pos = state.skipSpaces(pos);
|
||
|
||
if (pos < max) { continue; }
|
||
|
||
haveEndMarker = true;
|
||
// found!
|
||
break;
|
||
}
|
||
|
||
// If a fence has heading spaces, they should be removed from its inner block
|
||
len = state.sCount[startLine];
|
||
|
||
state.line = nextLine + (haveEndMarker ? 1 : 0);
|
||
|
||
token = state.push('fence', 'code', 0);
|
||
token.info = params;
|
||
token.content = state.getLines(startLine + 1, nextLine, len, true);
|
||
token.markup = markup;
|
||
token.map = [ startLine, state.line ];
|
||
|
||
return true;
|
||
};
|
||
|
||
var isSpace$9 = utils$1.isSpace;
|
||
|
||
|
||
var blockquote = function blockquote(state, startLine, endLine, silent) {
|
||
var adjustTab,
|
||
ch,
|
||
i,
|
||
initial,
|
||
l,
|
||
lastLineEmpty,
|
||
lines,
|
||
nextLine,
|
||
offset,
|
||
oldBMarks,
|
||
oldBSCount,
|
||
oldIndent,
|
||
oldParentType,
|
||
oldSCount,
|
||
oldTShift,
|
||
spaceAfterMarker,
|
||
terminate,
|
||
terminatorRules,
|
||
token,
|
||
isOutdented,
|
||
oldLineMax = state.lineMax,
|
||
pos = state.bMarks[startLine] + state.tShift[startLine],
|
||
max = state.eMarks[startLine];
|
||
|
||
// if it's indented more than 3 spaces, it should be a code block
|
||
if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }
|
||
|
||
// check the block quote marker
|
||
if (state.src.charCodeAt(pos++) !== 0x3E/* > */) { return false; }
|
||
|
||
// we know that it's going to be a valid blockquote,
|
||
// so no point trying to find the end of it in silent mode
|
||
if (silent) { return true; }
|
||
|
||
// set offset past spaces and ">"
|
||
initial = offset = state.sCount[startLine] + 1;
|
||
|
||
// skip one optional space after '>'
|
||
if (state.src.charCodeAt(pos) === 0x20 /* space */) {
|
||
// ' > test '
|
||
// ^ -- position start of line here:
|
||
pos++;
|
||
initial++;
|
||
offset++;
|
||
adjustTab = false;
|
||
spaceAfterMarker = true;
|
||
} else if (state.src.charCodeAt(pos) === 0x09 /* tab */) {
|
||
spaceAfterMarker = true;
|
||
|
||
if ((state.bsCount[startLine] + offset) % 4 === 3) {
|
||
// ' >\t test '
|
||
// ^ -- position start of line here (tab has width===1)
|
||
pos++;
|
||
initial++;
|
||
offset++;
|
||
adjustTab = false;
|
||
} else {
|
||
// ' >\t test '
|
||
// ^ -- position start of line here + shift bsCount slightly
|
||
// to make extra space appear
|
||
adjustTab = true;
|
||
}
|
||
} else {
|
||
spaceAfterMarker = false;
|
||
}
|
||
|
||
oldBMarks = [ state.bMarks[startLine] ];
|
||
state.bMarks[startLine] = pos;
|
||
|
||
while (pos < max) {
|
||
ch = state.src.charCodeAt(pos);
|
||
|
||
if (isSpace$9(ch)) {
|
||
if (ch === 0x09) {
|
||
offset += 4 - (offset + state.bsCount[startLine] + (adjustTab ? 1 : 0)) % 4;
|
||
} else {
|
||
offset++;
|
||
}
|
||
} else {
|
||
break;
|
||
}
|
||
|
||
pos++;
|
||
}
|
||
|
||
oldBSCount = [ state.bsCount[startLine] ];
|
||
state.bsCount[startLine] = state.sCount[startLine] + 1 + (spaceAfterMarker ? 1 : 0);
|
||
|
||
lastLineEmpty = pos >= max;
|
||
|
||
oldSCount = [ state.sCount[startLine] ];
|
||
state.sCount[startLine] = offset - initial;
|
||
|
||
oldTShift = [ state.tShift[startLine] ];
|
||
state.tShift[startLine] = pos - state.bMarks[startLine];
|
||
|
||
terminatorRules = state.md.block.ruler.getRules('blockquote');
|
||
|
||
oldParentType = state.parentType;
|
||
state.parentType = 'blockquote';
|
||
|
||
// Search the end of the block
|
||
//
|
||
// Block ends with either:
|
||
// 1. an empty line outside:
|
||
// ```
|
||
// > test
|
||
//
|
||
// ```
|
||
// 2. an empty line inside:
|
||
// ```
|
||
// >
|
||
// test
|
||
// ```
|
||
// 3. another tag:
|
||
// ```
|
||
// > test
|
||
// - - -
|
||
// ```
|
||
for (nextLine = startLine + 1; nextLine < endLine; nextLine++) {
|
||
// check if it's outdented, i.e. it's inside list item and indented
|
||
// less than said list item:
|
||
//
|
||
// ```
|
||
// 1. anything
|
||
// > current blockquote
|
||
// 2. checking this line
|
||
// ```
|
||
isOutdented = state.sCount[nextLine] < state.blkIndent;
|
||
|
||
pos = state.bMarks[nextLine] + state.tShift[nextLine];
|
||
max = state.eMarks[nextLine];
|
||
|
||
if (pos >= max) {
|
||
// Case 1: line is not inside the blockquote, and this line is empty.
|
||
break;
|
||
}
|
||
|
||
if (state.src.charCodeAt(pos++) === 0x3E/* > */ && !isOutdented) {
|
||
// This line is inside the blockquote.
|
||
|
||
// set offset past spaces and ">"
|
||
initial = offset = state.sCount[nextLine] + 1;
|
||
|
||
// skip one optional space after '>'
|
||
if (state.src.charCodeAt(pos) === 0x20 /* space */) {
|
||
// ' > test '
|
||
// ^ -- position start of line here:
|
||
pos++;
|
||
initial++;
|
||
offset++;
|
||
adjustTab = false;
|
||
spaceAfterMarker = true;
|
||
} else if (state.src.charCodeAt(pos) === 0x09 /* tab */) {
|
||
spaceAfterMarker = true;
|
||
|
||
if ((state.bsCount[nextLine] + offset) % 4 === 3) {
|
||
// ' >\t test '
|
||
// ^ -- position start of line here (tab has width===1)
|
||
pos++;
|
||
initial++;
|
||
offset++;
|
||
adjustTab = false;
|
||
} else {
|
||
// ' >\t test '
|
||
// ^ -- position start of line here + shift bsCount slightly
|
||
// to make extra space appear
|
||
adjustTab = true;
|
||
}
|
||
} else {
|
||
spaceAfterMarker = false;
|
||
}
|
||
|
||
oldBMarks.push(state.bMarks[nextLine]);
|
||
state.bMarks[nextLine] = pos;
|
||
|
||
while (pos < max) {
|
||
ch = state.src.charCodeAt(pos);
|
||
|
||
if (isSpace$9(ch)) {
|
||
if (ch === 0x09) {
|
||
offset += 4 - (offset + state.bsCount[nextLine] + (adjustTab ? 1 : 0)) % 4;
|
||
} else {
|
||
offset++;
|
||
}
|
||
} else {
|
||
break;
|
||
}
|
||
|
||
pos++;
|
||
}
|
||
|
||
lastLineEmpty = pos >= max;
|
||
|
||
oldBSCount.push(state.bsCount[nextLine]);
|
||
state.bsCount[nextLine] = state.sCount[nextLine] + 1 + (spaceAfterMarker ? 1 : 0);
|
||
|
||
oldSCount.push(state.sCount[nextLine]);
|
||
state.sCount[nextLine] = offset - initial;
|
||
|
||
oldTShift.push(state.tShift[nextLine]);
|
||
state.tShift[nextLine] = pos - state.bMarks[nextLine];
|
||
continue;
|
||
}
|
||
|
||
// Case 2: line is not inside the blockquote, and the last line was empty.
|
||
if (lastLineEmpty) { break; }
|
||
|
||
// Case 3: another tag found.
|
||
terminate = false;
|
||
for (i = 0, l = terminatorRules.length; i < l; i++) {
|
||
if (terminatorRules[i](state, nextLine, endLine, true)) {
|
||
terminate = true;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (terminate) {
|
||
// Quirk to enforce "hard termination mode" for paragraphs;
|
||
// normally if you call `tokenize(state, startLine, nextLine)`,
|
||
// paragraphs will look below nextLine for paragraph continuation,
|
||
// but if blockquote is terminated by another tag, they shouldn't
|
||
state.lineMax = nextLine;
|
||
|
||
if (state.blkIndent !== 0) {
|
||
// state.blkIndent was non-zero, we now set it to zero,
|
||
// so we need to re-calculate all offsets to appear as
|
||
// if indent wasn't changed
|
||
oldBMarks.push(state.bMarks[nextLine]);
|
||
oldBSCount.push(state.bsCount[nextLine]);
|
||
oldTShift.push(state.tShift[nextLine]);
|
||
oldSCount.push(state.sCount[nextLine]);
|
||
state.sCount[nextLine] -= state.blkIndent;
|
||
}
|
||
|
||
break;
|
||
}
|
||
|
||
oldBMarks.push(state.bMarks[nextLine]);
|
||
oldBSCount.push(state.bsCount[nextLine]);
|
||
oldTShift.push(state.tShift[nextLine]);
|
||
oldSCount.push(state.sCount[nextLine]);
|
||
|
||
// A negative indentation means that this is a paragraph continuation
|
||
//
|
||
state.sCount[nextLine] = -1;
|
||
}
|
||
|
||
oldIndent = state.blkIndent;
|
||
state.blkIndent = 0;
|
||
|
||
token = state.push('blockquote_open', 'blockquote', 1);
|
||
token.markup = '>';
|
||
token.map = lines = [ startLine, 0 ];
|
||
|
||
state.md.block.tokenize(state, startLine, nextLine);
|
||
|
||
token = state.push('blockquote_close', 'blockquote', -1);
|
||
token.markup = '>';
|
||
|
||
state.lineMax = oldLineMax;
|
||
state.parentType = oldParentType;
|
||
lines[1] = state.line;
|
||
|
||
// Restore original tShift; this might not be necessary since the parser
|
||
// has already been here, but just to make sure we can do that.
|
||
for (i = 0; i < oldTShift.length; i++) {
|
||
state.bMarks[i + startLine] = oldBMarks[i];
|
||
state.tShift[i + startLine] = oldTShift[i];
|
||
state.sCount[i + startLine] = oldSCount[i];
|
||
state.bsCount[i + startLine] = oldBSCount[i];
|
||
}
|
||
state.blkIndent = oldIndent;
|
||
|
||
return true;
|
||
};
|
||
|
||
var isSpace$8 = utils$1.isSpace;
|
||
|
||
|
||
var hr = function hr(state, startLine, endLine, silent) {
|
||
var marker, cnt, ch, token,
|
||
pos = state.bMarks[startLine] + state.tShift[startLine],
|
||
max = state.eMarks[startLine];
|
||
|
||
// if it's indented more than 3 spaces, it should be a code block
|
||
if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }
|
||
|
||
marker = state.src.charCodeAt(pos++);
|
||
|
||
// Check hr marker
|
||
if (marker !== 0x2A/* * */ &&
|
||
marker !== 0x2D/* - */ &&
|
||
marker !== 0x5F/* _ */) {
|
||
return false;
|
||
}
|
||
|
||
// markers can be mixed with spaces, but there should be at least 3 of them
|
||
|
||
cnt = 1;
|
||
while (pos < max) {
|
||
ch = state.src.charCodeAt(pos++);
|
||
if (ch !== marker && !isSpace$8(ch)) { return false; }
|
||
if (ch === marker) { cnt++; }
|
||
}
|
||
|
||
if (cnt < 3) { return false; }
|
||
|
||
if (silent) { return true; }
|
||
|
||
state.line = startLine + 1;
|
||
|
||
token = state.push('hr', 'hr', 0);
|
||
token.map = [ startLine, state.line ];
|
||
token.markup = Array(cnt + 1).join(String.fromCharCode(marker));
|
||
|
||
return true;
|
||
};
|
||
|
||
var isSpace$7 = utils$1.isSpace;
|
||
|
||
|
||
// Search `[-+*][\n ]`, returns next pos after marker on success
|
||
// or -1 on fail.
|
||
function skipBulletListMarker(state, startLine) {
|
||
var marker, pos, max, ch;
|
||
|
||
pos = state.bMarks[startLine] + state.tShift[startLine];
|
||
max = state.eMarks[startLine];
|
||
|
||
marker = state.src.charCodeAt(pos++);
|
||
// Check bullet
|
||
if (marker !== 0x2A/* * */ &&
|
||
marker !== 0x2D/* - */ &&
|
||
marker !== 0x2B/* + */) {
|
||
return -1;
|
||
}
|
||
|
||
if (pos < max) {
|
||
ch = state.src.charCodeAt(pos);
|
||
|
||
if (!isSpace$7(ch)) {
|
||
// " -test " - is not a list item
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
return pos;
|
||
}
|
||
|
||
// Search `\d+[.)][\n ]`, returns next pos after marker on success
|
||
// or -1 on fail.
|
||
function skipOrderedListMarker(state, startLine) {
|
||
var ch,
|
||
start = state.bMarks[startLine] + state.tShift[startLine],
|
||
pos = start,
|
||
max = state.eMarks[startLine];
|
||
|
||
// List marker should have at least 2 chars (digit + dot)
|
||
if (pos + 1 >= max) { return -1; }
|
||
|
||
ch = state.src.charCodeAt(pos++);
|
||
|
||
if (ch < 0x30/* 0 */ || ch > 0x39/* 9 */) { return -1; }
|
||
|
||
for (;;) {
|
||
// EOL -> fail
|
||
if (pos >= max) { return -1; }
|
||
|
||
ch = state.src.charCodeAt(pos++);
|
||
|
||
if (ch >= 0x30/* 0 */ && ch <= 0x39/* 9 */) {
|
||
|
||
// List marker should have no more than 9 digits
|
||
// (prevents integer overflow in browsers)
|
||
if (pos - start >= 10) { return -1; }
|
||
|
||
continue;
|
||
}
|
||
|
||
// found valid marker
|
||
if (ch === 0x29/* ) */ || ch === 0x2e/* . */) {
|
||
break;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
|
||
if (pos < max) {
|
||
ch = state.src.charCodeAt(pos);
|
||
|
||
if (!isSpace$7(ch)) {
|
||
// " 1.test " - is not a list item
|
||
return -1;
|
||
}
|
||
}
|
||
return pos;
|
||
}
|
||
|
||
function markTightParagraphs(state, idx) {
|
||
var i, l,
|
||
level = state.level + 2;
|
||
|
||
for (i = idx + 2, l = state.tokens.length - 2; i < l; i++) {
|
||
if (state.tokens[i].level === level && state.tokens[i].type === 'paragraph_open') {
|
||
state.tokens[i + 2].hidden = true;
|
||
state.tokens[i].hidden = true;
|
||
i += 2;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
var list = function list(state, startLine, endLine, silent) {
|
||
var ch,
|
||
contentStart,
|
||
i,
|
||
indent,
|
||
indentAfterMarker,
|
||
initial,
|
||
isOrdered,
|
||
itemLines,
|
||
l,
|
||
listLines,
|
||
listTokIdx,
|
||
markerCharCode,
|
||
markerValue,
|
||
max,
|
||
nextLine,
|
||
offset,
|
||
oldListIndent,
|
||
oldParentType,
|
||
oldSCount,
|
||
oldTShift,
|
||
oldTight,
|
||
pos,
|
||
posAfterMarker,
|
||
prevEmptyEnd,
|
||
start,
|
||
terminate,
|
||
terminatorRules,
|
||
token,
|
||
isTerminatingParagraph = false,
|
||
tight = true;
|
||
|
||
// if it's indented more than 3 spaces, it should be a code block
|
||
if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }
|
||
|
||
// Special case:
|
||
// - item 1
|
||
// - item 2
|
||
// - item 3
|
||
// - item 4
|
||
// - this one is a paragraph continuation
|
||
if (state.listIndent >= 0 &&
|
||
state.sCount[startLine] - state.listIndent >= 4 &&
|
||
state.sCount[startLine] < state.blkIndent) {
|
||
return false;
|
||
}
|
||
|
||
// limit conditions when list can interrupt
|
||
// a paragraph (validation mode only)
|
||
if (silent && state.parentType === 'paragraph') {
|
||
// Next list item should still terminate previous list item;
|
||
//
|
||
// This code can fail if plugins use blkIndent as well as lists,
|
||
// but I hope the spec gets fixed long before that happens.
|
||
//
|
||
if (state.sCount[startLine] >= state.blkIndent) {
|
||
isTerminatingParagraph = true;
|
||
}
|
||
}
|
||
|
||
// Detect list type and position after marker
|
||
if ((posAfterMarker = skipOrderedListMarker(state, startLine)) >= 0) {
|
||
isOrdered = true;
|
||
start = state.bMarks[startLine] + state.tShift[startLine];
|
||
markerValue = Number(state.src.slice(start, posAfterMarker - 1));
|
||
|
||
// If we're starting a new ordered list right after
|
||
// a paragraph, it should start with 1.
|
||
if (isTerminatingParagraph && markerValue !== 1) return false;
|
||
|
||
} else if ((posAfterMarker = skipBulletListMarker(state, startLine)) >= 0) {
|
||
isOrdered = false;
|
||
|
||
} else {
|
||
return false;
|
||
}
|
||
|
||
// If we're starting a new unordered list right after
|
||
// a paragraph, first line should not be empty.
|
||
if (isTerminatingParagraph) {
|
||
if (state.skipSpaces(posAfterMarker) >= state.eMarks[startLine]) return false;
|
||
}
|
||
|
||
// We should terminate list on style change. Remember first one to compare.
|
||
markerCharCode = state.src.charCodeAt(posAfterMarker - 1);
|
||
|
||
// For validation mode we can terminate immediately
|
||
if (silent) { return true; }
|
||
|
||
// Start list
|
||
listTokIdx = state.tokens.length;
|
||
|
||
if (isOrdered) {
|
||
token = state.push('ordered_list_open', 'ol', 1);
|
||
if (markerValue !== 1) {
|
||
token.attrs = [ [ 'start', markerValue ] ];
|
||
}
|
||
|
||
} else {
|
||
token = state.push('bullet_list_open', 'ul', 1);
|
||
}
|
||
|
||
token.map = listLines = [ startLine, 0 ];
|
||
token.markup = String.fromCharCode(markerCharCode);
|
||
|
||
//
|
||
// Iterate list items
|
||
//
|
||
|
||
nextLine = startLine;
|
||
prevEmptyEnd = false;
|
||
terminatorRules = state.md.block.ruler.getRules('list');
|
||
|
||
oldParentType = state.parentType;
|
||
state.parentType = 'list';
|
||
|
||
while (nextLine < endLine) {
|
||
pos = posAfterMarker;
|
||
max = state.eMarks[nextLine];
|
||
|
||
initial = offset = state.sCount[nextLine] + posAfterMarker - (state.bMarks[startLine] + state.tShift[startLine]);
|
||
|
||
while (pos < max) {
|
||
ch = state.src.charCodeAt(pos);
|
||
|
||
if (ch === 0x09) {
|
||
offset += 4 - (offset + state.bsCount[nextLine]) % 4;
|
||
} else if (ch === 0x20) {
|
||
offset++;
|
||
} else {
|
||
break;
|
||
}
|
||
|
||
pos++;
|
||
}
|
||
|
||
contentStart = pos;
|
||
|
||
if (contentStart >= max) {
|
||
// trimming space in "- \n 3" case, indent is 1 here
|
||
indentAfterMarker = 1;
|
||
} else {
|
||
indentAfterMarker = offset - initial;
|
||
}
|
||
|
||
// If we have more than 4 spaces, the indent is 1
|
||
// (the rest is just indented code block)
|
||
if (indentAfterMarker > 4) { indentAfterMarker = 1; }
|
||
|
||
// " - test"
|
||
// ^^^^^ - calculating total length of this thing
|
||
indent = initial + indentAfterMarker;
|
||
|
||
// Run subparser & write tokens
|
||
token = state.push('list_item_open', 'li', 1);
|
||
token.markup = String.fromCharCode(markerCharCode);
|
||
token.map = itemLines = [ startLine, 0 ];
|
||
if (isOrdered) {
|
||
token.info = state.src.slice(start, posAfterMarker - 1);
|
||
}
|
||
|
||
// change current state, then restore it after parser subcall
|
||
oldTight = state.tight;
|
||
oldTShift = state.tShift[startLine];
|
||
oldSCount = state.sCount[startLine];
|
||
|
||
// - example list
|
||
// ^ listIndent position will be here
|
||
// ^ blkIndent position will be here
|
||
//
|
||
oldListIndent = state.listIndent;
|
||
state.listIndent = state.blkIndent;
|
||
state.blkIndent = indent;
|
||
|
||
state.tight = true;
|
||
state.tShift[startLine] = contentStart - state.bMarks[startLine];
|
||
state.sCount[startLine] = offset;
|
||
|
||
if (contentStart >= max && state.isEmpty(startLine + 1)) {
|
||
// workaround for this case
|
||
// (list item is empty, list terminates before "foo"):
|
||
// ~~~~~~~~
|
||
// -
|
||
//
|
||
// foo
|
||
// ~~~~~~~~
|
||
state.line = Math.min(state.line + 2, endLine);
|
||
} else {
|
||
state.md.block.tokenize(state, startLine, endLine, true);
|
||
}
|
||
|
||
// If any of list item is tight, mark list as tight
|
||
if (!state.tight || prevEmptyEnd) {
|
||
tight = false;
|
||
}
|
||
// Item become loose if finish with empty line,
|
||
// but we should filter last element, because it means list finish
|
||
prevEmptyEnd = (state.line - startLine) > 1 && state.isEmpty(state.line - 1);
|
||
|
||
state.blkIndent = state.listIndent;
|
||
state.listIndent = oldListIndent;
|
||
state.tShift[startLine] = oldTShift;
|
||
state.sCount[startLine] = oldSCount;
|
||
state.tight = oldTight;
|
||
|
||
token = state.push('list_item_close', 'li', -1);
|
||
token.markup = String.fromCharCode(markerCharCode);
|
||
|
||
nextLine = startLine = state.line;
|
||
itemLines[1] = nextLine;
|
||
contentStart = state.bMarks[startLine];
|
||
|
||
if (nextLine >= endLine) { break; }
|
||
|
||
//
|
||
// Try to check if list is terminated or continued.
|
||
//
|
||
if (state.sCount[nextLine] < state.blkIndent) { break; }
|
||
|
||
// if it's indented more than 3 spaces, it should be a code block
|
||
if (state.sCount[startLine] - state.blkIndent >= 4) { break; }
|
||
|
||
// fail if terminating block found
|
||
terminate = false;
|
||
for (i = 0, l = terminatorRules.length; i < l; i++) {
|
||
if (terminatorRules[i](state, nextLine, endLine, true)) {
|
||
terminate = true;
|
||
break;
|
||
}
|
||
}
|
||
if (terminate) { break; }
|
||
|
||
// fail if list has another type
|
||
if (isOrdered) {
|
||
posAfterMarker = skipOrderedListMarker(state, nextLine);
|
||
if (posAfterMarker < 0) { break; }
|
||
start = state.bMarks[nextLine] + state.tShift[nextLine];
|
||
} else {
|
||
posAfterMarker = skipBulletListMarker(state, nextLine);
|
||
if (posAfterMarker < 0) { break; }
|
||
}
|
||
|
||
if (markerCharCode !== state.src.charCodeAt(posAfterMarker - 1)) { break; }
|
||
}
|
||
|
||
// Finalize list
|
||
if (isOrdered) {
|
||
token = state.push('ordered_list_close', 'ol', -1);
|
||
} else {
|
||
token = state.push('bullet_list_close', 'ul', -1);
|
||
}
|
||
token.markup = String.fromCharCode(markerCharCode);
|
||
|
||
listLines[1] = nextLine;
|
||
state.line = nextLine;
|
||
|
||
state.parentType = oldParentType;
|
||
|
||
// mark paragraphs tight if needed
|
||
if (tight) {
|
||
markTightParagraphs(state, listTokIdx);
|
||
}
|
||
|
||
return true;
|
||
};
|
||
|
||
var normalizeReference$2 = utils$1.normalizeReference;
|
||
var isSpace$6 = utils$1.isSpace;
|
||
|
||
|
||
var reference = function reference(state, startLine, _endLine, silent) {
|
||
var ch,
|
||
destEndPos,
|
||
destEndLineNo,
|
||
endLine,
|
||
href,
|
||
i,
|
||
l,
|
||
label,
|
||
labelEnd,
|
||
oldParentType,
|
||
res,
|
||
start,
|
||
str,
|
||
terminate,
|
||
terminatorRules,
|
||
title,
|
||
lines = 0,
|
||
pos = state.bMarks[startLine] + state.tShift[startLine],
|
||
max = state.eMarks[startLine],
|
||
nextLine = startLine + 1;
|
||
|
||
// if it's indented more than 3 spaces, it should be a code block
|
||
if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }
|
||
|
||
if (state.src.charCodeAt(pos) !== 0x5B/* [ */) { return false; }
|
||
|
||
// Simple check to quickly interrupt scan on [link](url) at the start of line.
|
||
// Can be useful on practice: https://github.com/markdown-it/markdown-it/issues/54
|
||
while (++pos < max) {
|
||
if (state.src.charCodeAt(pos) === 0x5D /* ] */ &&
|
||
state.src.charCodeAt(pos - 1) !== 0x5C/* \ */) {
|
||
if (pos + 1 === max) { return false; }
|
||
if (state.src.charCodeAt(pos + 1) !== 0x3A/* : */) { return false; }
|
||
break;
|
||
}
|
||
}
|
||
|
||
endLine = state.lineMax;
|
||
|
||
// jump line-by-line until empty one or EOF
|
||
terminatorRules = state.md.block.ruler.getRules('reference');
|
||
|
||
oldParentType = state.parentType;
|
||
state.parentType = 'reference';
|
||
|
||
for (; nextLine < endLine && !state.isEmpty(nextLine); nextLine++) {
|
||
// this would be a code block normally, but after paragraph
|
||
// it's considered a lazy continuation regardless of what's there
|
||
if (state.sCount[nextLine] - state.blkIndent > 3) { continue; }
|
||
|
||
// quirk for blockquotes, this line should already be checked by that rule
|
||
if (state.sCount[nextLine] < 0) { continue; }
|
||
|
||
// Some tags can terminate paragraph without empty line.
|
||
terminate = false;
|
||
for (i = 0, l = terminatorRules.length; i < l; i++) {
|
||
if (terminatorRules[i](state, nextLine, endLine, true)) {
|
||
terminate = true;
|
||
break;
|
||
}
|
||
}
|
||
if (terminate) { break; }
|
||
}
|
||
|
||
str = state.getLines(startLine, nextLine, state.blkIndent, false).trim();
|
||
max = str.length;
|
||
|
||
for (pos = 1; pos < max; pos++) {
|
||
ch = str.charCodeAt(pos);
|
||
if (ch === 0x5B /* [ */) {
|
||
return false;
|
||
} else if (ch === 0x5D /* ] */) {
|
||
labelEnd = pos;
|
||
break;
|
||
} else if (ch === 0x0A /* \n */) {
|
||
lines++;
|
||
} else if (ch === 0x5C /* \ */) {
|
||
pos++;
|
||
if (pos < max && str.charCodeAt(pos) === 0x0A) {
|
||
lines++;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (labelEnd < 0 || str.charCodeAt(labelEnd + 1) !== 0x3A/* : */) { return false; }
|
||
|
||
// [label]: destination 'title'
|
||
// ^^^ skip optional whitespace here
|
||
for (pos = labelEnd + 2; pos < max; pos++) {
|
||
ch = str.charCodeAt(pos);
|
||
if (ch === 0x0A) {
|
||
lines++;
|
||
} else if (isSpace$6(ch)) ; else {
|
||
break;
|
||
}
|
||
}
|
||
|
||
// [label]: destination 'title'
|
||
// ^^^^^^^^^^^ parse this
|
||
res = state.md.helpers.parseLinkDestination(str, pos, max);
|
||
if (!res.ok) { return false; }
|
||
|
||
href = state.md.normalizeLink(res.str);
|
||
if (!state.md.validateLink(href)) { return false; }
|
||
|
||
pos = res.pos;
|
||
lines += res.lines;
|
||
|
||
// save cursor state, we could require to rollback later
|
||
destEndPos = pos;
|
||
destEndLineNo = lines;
|
||
|
||
// [label]: destination 'title'
|
||
// ^^^ skipping those spaces
|
||
start = pos;
|
||
for (; pos < max; pos++) {
|
||
ch = str.charCodeAt(pos);
|
||
if (ch === 0x0A) {
|
||
lines++;
|
||
} else if (isSpace$6(ch)) ; else {
|
||
break;
|
||
}
|
||
}
|
||
|
||
// [label]: destination 'title'
|
||
// ^^^^^^^ parse this
|
||
res = state.md.helpers.parseLinkTitle(str, pos, max);
|
||
if (pos < max && start !== pos && res.ok) {
|
||
title = res.str;
|
||
pos = res.pos;
|
||
lines += res.lines;
|
||
} else {
|
||
title = '';
|
||
pos = destEndPos;
|
||
lines = destEndLineNo;
|
||
}
|
||
|
||
// skip trailing spaces until the rest of the line
|
||
while (pos < max) {
|
||
ch = str.charCodeAt(pos);
|
||
if (!isSpace$6(ch)) { break; }
|
||
pos++;
|
||
}
|
||
|
||
if (pos < max && str.charCodeAt(pos) !== 0x0A) {
|
||
if (title) {
|
||
// garbage at the end of the line after title,
|
||
// but it could still be a valid reference if we roll back
|
||
title = '';
|
||
pos = destEndPos;
|
||
lines = destEndLineNo;
|
||
while (pos < max) {
|
||
ch = str.charCodeAt(pos);
|
||
if (!isSpace$6(ch)) { break; }
|
||
pos++;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (pos < max && str.charCodeAt(pos) !== 0x0A) {
|
||
// garbage at the end of the line
|
||
return false;
|
||
}
|
||
|
||
label = normalizeReference$2(str.slice(1, labelEnd));
|
||
if (!label) {
|
||
// CommonMark 0.20 disallows empty labels
|
||
return false;
|
||
}
|
||
|
||
// Reference can not terminate anything. This check is for safety only.
|
||
/*istanbul ignore if*/
|
||
if (silent) { return true; }
|
||
|
||
if (typeof state.env.references === 'undefined') {
|
||
state.env.references = {};
|
||
}
|
||
if (typeof state.env.references[label] === 'undefined') {
|
||
state.env.references[label] = { title: title, href: href };
|
||
}
|
||
|
||
state.parentType = oldParentType;
|
||
|
||
state.line = startLine + lines + 1;
|
||
return true;
|
||
};
|
||
|
||
var html_blocks = [
|
||
'address',
|
||
'article',
|
||
'aside',
|
||
'base',
|
||
'basefont',
|
||
'blockquote',
|
||
'body',
|
||
'caption',
|
||
'center',
|
||
'col',
|
||
'colgroup',
|
||
'dd',
|
||
'details',
|
||
'dialog',
|
||
'dir',
|
||
'div',
|
||
'dl',
|
||
'dt',
|
||
'fieldset',
|
||
'figcaption',
|
||
'figure',
|
||
'footer',
|
||
'form',
|
||
'frame',
|
||
'frameset',
|
||
'h1',
|
||
'h2',
|
||
'h3',
|
||
'h4',
|
||
'h5',
|
||
'h6',
|
||
'head',
|
||
'header',
|
||
'hr',
|
||
'html',
|
||
'iframe',
|
||
'legend',
|
||
'li',
|
||
'link',
|
||
'main',
|
||
'menu',
|
||
'menuitem',
|
||
'nav',
|
||
'noframes',
|
||
'ol',
|
||
'optgroup',
|
||
'option',
|
||
'p',
|
||
'param',
|
||
'section',
|
||
'source',
|
||
'summary',
|
||
'table',
|
||
'tbody',
|
||
'td',
|
||
'tfoot',
|
||
'th',
|
||
'thead',
|
||
'title',
|
||
'tr',
|
||
'track',
|
||
'ul'
|
||
];
|
||
|
||
var html_re = {};
|
||
|
||
var attr_name = '[a-zA-Z_:][a-zA-Z0-9:._-]*';
|
||
|
||
var unquoted = '[^"\'=<>`\\x00-\\x20]+';
|
||
var single_quoted = "'[^']*'";
|
||
var double_quoted = '"[^"]*"';
|
||
|
||
var attr_value = '(?:' + unquoted + '|' + single_quoted + '|' + double_quoted + ')';
|
||
|
||
var attribute = '(?:\\s+' + attr_name + '(?:\\s*=\\s*' + attr_value + ')?)';
|
||
|
||
var open_tag = '<[A-Za-z][A-Za-z0-9\\-]*' + attribute + '*\\s*\\/?>';
|
||
|
||
var close_tag = '<\\/[A-Za-z][A-Za-z0-9\\-]*\\s*>';
|
||
var comment = '<!---->|<!--(?:-?[^>-])(?:-?[^-])*-->';
|
||
var processing = '<[?][\\s\\S]*?[?]>';
|
||
var declaration = '<![A-Z]+\\s+[^>]*>';
|
||
var cdata = '<!\\[CDATA\\[[\\s\\S]*?\\]\\]>';
|
||
|
||
var HTML_TAG_RE$1 = new RegExp('^(?:' + open_tag + '|' + close_tag + '|' + comment +
|
||
'|' + processing + '|' + declaration + '|' + cdata + ')');
|
||
var HTML_OPEN_CLOSE_TAG_RE$1 = new RegExp('^(?:' + open_tag + '|' + close_tag + ')');
|
||
|
||
html_re.HTML_TAG_RE = HTML_TAG_RE$1;
|
||
html_re.HTML_OPEN_CLOSE_TAG_RE = HTML_OPEN_CLOSE_TAG_RE$1;
|
||
|
||
var block_names = html_blocks;
|
||
var HTML_OPEN_CLOSE_TAG_RE = html_re.HTML_OPEN_CLOSE_TAG_RE;
|
||
|
||
// An array of opening and corresponding closing sequences for html tags,
|
||
// last argument defines whether it can terminate a paragraph or not
|
||
//
|
||
var HTML_SEQUENCES = [
|
||
[ /^<(script|pre|style|textarea)(?=(\s|>|$))/i, /<\/(script|pre|style|textarea)>/i, true ],
|
||
[ /^<!--/, /-->/, true ],
|
||
[ /^<\?/, /\?>/, true ],
|
||
[ /^<![A-Z]/, />/, true ],
|
||
[ /^<!\[CDATA\[/, /\]\]>/, true ],
|
||
[ new RegExp('^</?(' + block_names.join('|') + ')(?=(\\s|/?>|$))', 'i'), /^$/, true ],
|
||
[ new RegExp(HTML_OPEN_CLOSE_TAG_RE.source + '\\s*$'), /^$/, false ]
|
||
];
|
||
|
||
|
||
var html_block = function html_block(state, startLine, endLine, silent) {
|
||
var i, nextLine, token, lineText,
|
||
pos = state.bMarks[startLine] + state.tShift[startLine],
|
||
max = state.eMarks[startLine];
|
||
|
||
// if it's indented more than 3 spaces, it should be a code block
|
||
if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }
|
||
|
||
if (!state.md.options.html) { return false; }
|
||
|
||
if (state.src.charCodeAt(pos) !== 0x3C/* < */) { return false; }
|
||
|
||
lineText = state.src.slice(pos, max);
|
||
|
||
for (i = 0; i < HTML_SEQUENCES.length; i++) {
|
||
if (HTML_SEQUENCES[i][0].test(lineText)) { break; }
|
||
}
|
||
|
||
if (i === HTML_SEQUENCES.length) { return false; }
|
||
|
||
if (silent) {
|
||
// true if this sequence can be a terminator, false otherwise
|
||
return HTML_SEQUENCES[i][2];
|
||
}
|
||
|
||
nextLine = startLine + 1;
|
||
|
||
// If we are here - we detected HTML block.
|
||
// Let's roll down till block end.
|
||
if (!HTML_SEQUENCES[i][1].test(lineText)) {
|
||
for (; nextLine < endLine; nextLine++) {
|
||
if (state.sCount[nextLine] < state.blkIndent) { break; }
|
||
|
||
pos = state.bMarks[nextLine] + state.tShift[nextLine];
|
||
max = state.eMarks[nextLine];
|
||
lineText = state.src.slice(pos, max);
|
||
|
||
if (HTML_SEQUENCES[i][1].test(lineText)) {
|
||
if (lineText.length !== 0) { nextLine++; }
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
state.line = nextLine;
|
||
|
||
token = state.push('html_block', '', 0);
|
||
token.map = [ startLine, nextLine ];
|
||
token.content = state.getLines(startLine, nextLine, state.blkIndent, true);
|
||
|
||
return true;
|
||
};
|
||
|
||
var isSpace$5 = utils$1.isSpace;
|
||
|
||
|
||
var heading = function heading(state, startLine, endLine, silent) {
|
||
var ch, level, tmp, token,
|
||
pos = state.bMarks[startLine] + state.tShift[startLine],
|
||
max = state.eMarks[startLine];
|
||
|
||
// if it's indented more than 3 spaces, it should be a code block
|
||
if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }
|
||
|
||
ch = state.src.charCodeAt(pos);
|
||
|
||
if (ch !== 0x23/* # */ || pos >= max) { return false; }
|
||
|
||
// count heading level
|
||
level = 1;
|
||
ch = state.src.charCodeAt(++pos);
|
||
while (ch === 0x23/* # */ && pos < max && level <= 6) {
|
||
level++;
|
||
ch = state.src.charCodeAt(++pos);
|
||
}
|
||
|
||
if (level > 6 || (pos < max && !isSpace$5(ch))) { return false; }
|
||
|
||
if (silent) { return true; }
|
||
|
||
// Let's cut tails like ' ### ' from the end of string
|
||
|
||
max = state.skipSpacesBack(max, pos);
|
||
tmp = state.skipCharsBack(max, 0x23, pos); // #
|
||
if (tmp > pos && isSpace$5(state.src.charCodeAt(tmp - 1))) {
|
||
max = tmp;
|
||
}
|
||
|
||
state.line = startLine + 1;
|
||
|
||
token = state.push('heading_open', 'h' + String(level), 1);
|
||
token.markup = '########'.slice(0, level);
|
||
token.map = [ startLine, state.line ];
|
||
|
||
token = state.push('inline', '', 0);
|
||
token.content = state.src.slice(pos, max).trim();
|
||
token.map = [ startLine, state.line ];
|
||
token.children = [];
|
||
|
||
token = state.push('heading_close', 'h' + String(level), -1);
|
||
token.markup = '########'.slice(0, level);
|
||
|
||
return true;
|
||
};
|
||
|
||
var lheading = function lheading(state, startLine, endLine/*, silent*/) {
|
||
var content, terminate, i, l, token, pos, max, level, marker,
|
||
nextLine = startLine + 1, oldParentType,
|
||
terminatorRules = state.md.block.ruler.getRules('paragraph');
|
||
|
||
// if it's indented more than 3 spaces, it should be a code block
|
||
if (state.sCount[startLine] - state.blkIndent >= 4) { return false; }
|
||
|
||
oldParentType = state.parentType;
|
||
state.parentType = 'paragraph'; // use paragraph to match terminatorRules
|
||
|
||
// jump line-by-line until empty one or EOF
|
||
for (; nextLine < endLine && !state.isEmpty(nextLine); nextLine++) {
|
||
// this would be a code block normally, but after paragraph
|
||
// it's considered a lazy continuation regardless of what's there
|
||
if (state.sCount[nextLine] - state.blkIndent > 3) { continue; }
|
||
|
||
//
|
||
// Check for underline in setext header
|
||
//
|
||
if (state.sCount[nextLine] >= state.blkIndent) {
|
||
pos = state.bMarks[nextLine] + state.tShift[nextLine];
|
||
max = state.eMarks[nextLine];
|
||
|
||
if (pos < max) {
|
||
marker = state.src.charCodeAt(pos);
|
||
|
||
if (marker === 0x2D/* - */ || marker === 0x3D/* = */) {
|
||
pos = state.skipChars(pos, marker);
|
||
pos = state.skipSpaces(pos);
|
||
|
||
if (pos >= max) {
|
||
level = (marker === 0x3D/* = */ ? 1 : 2);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// quirk for blockquotes, this line should already be checked by that rule
|
||
if (state.sCount[nextLine] < 0) { continue; }
|
||
|
||
// Some tags can terminate paragraph without empty line.
|
||
terminate = false;
|
||
for (i = 0, l = terminatorRules.length; i < l; i++) {
|
||
if (terminatorRules[i](state, nextLine, endLine, true)) {
|
||
terminate = true;
|
||
break;
|
||
}
|
||
}
|
||
if (terminate) { break; }
|
||
}
|
||
|
||
if (!level) {
|
||
// Didn't find valid underline
|
||
return false;
|
||
}
|
||
|
||
content = state.getLines(startLine, nextLine, state.blkIndent, false).trim();
|
||
|
||
state.line = nextLine + 1;
|
||
|
||
token = state.push('heading_open', 'h' + String(level), 1);
|
||
token.markup = String.fromCharCode(marker);
|
||
token.map = [ startLine, state.line ];
|
||
|
||
token = state.push('inline', '', 0);
|
||
token.content = content;
|
||
token.map = [ startLine, state.line - 1 ];
|
||
token.children = [];
|
||
|
||
token = state.push('heading_close', 'h' + String(level), -1);
|
||
token.markup = String.fromCharCode(marker);
|
||
|
||
state.parentType = oldParentType;
|
||
|
||
return true;
|
||
};
|
||
|
||
var paragraph = function paragraph(state, startLine/*, endLine*/) {
|
||
var content, terminate, i, l, token, oldParentType,
|
||
nextLine = startLine + 1,
|
||
terminatorRules = state.md.block.ruler.getRules('paragraph'),
|
||
endLine = state.lineMax;
|
||
|
||
oldParentType = state.parentType;
|
||
state.parentType = 'paragraph';
|
||
|
||
// jump line-by-line until empty one or EOF
|
||
for (; nextLine < endLine && !state.isEmpty(nextLine); nextLine++) {
|
||
// this would be a code block normally, but after paragraph
|
||
// it's considered a lazy continuation regardless of what's there
|
||
if (state.sCount[nextLine] - state.blkIndent > 3) { continue; }
|
||
|
||
// quirk for blockquotes, this line should already be checked by that rule
|
||
if (state.sCount[nextLine] < 0) { continue; }
|
||
|
||
// Some tags can terminate paragraph without empty line.
|
||
terminate = false;
|
||
for (i = 0, l = terminatorRules.length; i < l; i++) {
|
||
if (terminatorRules[i](state, nextLine, endLine, true)) {
|
||
terminate = true;
|
||
break;
|
||
}
|
||
}
|
||
if (terminate) { break; }
|
||
}
|
||
|
||
content = state.getLines(startLine, nextLine, state.blkIndent, false).trim();
|
||
|
||
state.line = nextLine;
|
||
|
||
token = state.push('paragraph_open', 'p', 1);
|
||
token.map = [ startLine, state.line ];
|
||
|
||
token = state.push('inline', '', 0);
|
||
token.content = content;
|
||
token.map = [ startLine, state.line ];
|
||
token.children = [];
|
||
|
||
token = state.push('paragraph_close', 'p', -1);
|
||
|
||
state.parentType = oldParentType;
|
||
|
||
return true;
|
||
};
|
||
|
||
var Token$1 = token;
|
||
var isSpace$4 = utils$1.isSpace;
|
||
|
||
|
||
function StateBlock(src, md, env, tokens) {
|
||
var ch, s, start, pos, len, indent, offset, indent_found;
|
||
|
||
this.src = src;
|
||
|
||
// link to parser instance
|
||
this.md = md;
|
||
|
||
this.env = env;
|
||
|
||
//
|
||
// Internal state vartiables
|
||
//
|
||
|
||
this.tokens = tokens;
|
||
|
||
this.bMarks = []; // line begin offsets for fast jumps
|
||
this.eMarks = []; // line end offsets for fast jumps
|
||
this.tShift = []; // offsets of the first non-space characters (tabs not expanded)
|
||
this.sCount = []; // indents for each line (tabs expanded)
|
||
|
||
// An amount of virtual spaces (tabs expanded) between beginning
|
||
// of each line (bMarks) and real beginning of that line.
|
||
//
|
||
// It exists only as a hack because blockquotes override bMarks
|
||
// losing information in the process.
|
||
//
|
||
// It's used only when expanding tabs, you can think about it as
|
||
// an initial tab length, e.g. bsCount=21 applied to string `\t123`
|
||
// means first tab should be expanded to 4-21%4 === 3 spaces.
|
||
//
|
||
this.bsCount = [];
|
||
|
||
// block parser variables
|
||
this.blkIndent = 0; // required block content indent (for example, if we are
|
||
// inside a list, it would be positioned after list marker)
|
||
this.line = 0; // line index in src
|
||
this.lineMax = 0; // lines count
|
||
this.tight = false; // loose/tight mode for lists
|
||
this.ddIndent = -1; // indent of the current dd block (-1 if there isn't any)
|
||
this.listIndent = -1; // indent of the current list block (-1 if there isn't any)
|
||
|
||
// can be 'blockquote', 'list', 'root', 'paragraph' or 'reference'
|
||
// used in lists to determine if they interrupt a paragraph
|
||
this.parentType = 'root';
|
||
|
||
this.level = 0;
|
||
|
||
// renderer
|
||
this.result = '';
|
||
|
||
// Create caches
|
||
// Generate markers.
|
||
s = this.src;
|
||
indent_found = false;
|
||
|
||
for (start = pos = indent = offset = 0, len = s.length; pos < len; pos++) {
|
||
ch = s.charCodeAt(pos);
|
||
|
||
if (!indent_found) {
|
||
if (isSpace$4(ch)) {
|
||
indent++;
|
||
|
||
if (ch === 0x09) {
|
||
offset += 4 - offset % 4;
|
||
} else {
|
||
offset++;
|
||
}
|
||
continue;
|
||
} else {
|
||
indent_found = true;
|
||
}
|
||
}
|
||
|
||
if (ch === 0x0A || pos === len - 1) {
|
||
if (ch !== 0x0A) { pos++; }
|
||
this.bMarks.push(start);
|
||
this.eMarks.push(pos);
|
||
this.tShift.push(indent);
|
||
this.sCount.push(offset);
|
||
this.bsCount.push(0);
|
||
|
||
indent_found = false;
|
||
indent = 0;
|
||
offset = 0;
|
||
start = pos + 1;
|
||
}
|
||
}
|
||
|
||
// Push fake entry to simplify cache bounds checks
|
||
this.bMarks.push(s.length);
|
||
this.eMarks.push(s.length);
|
||
this.tShift.push(0);
|
||
this.sCount.push(0);
|
||
this.bsCount.push(0);
|
||
|
||
this.lineMax = this.bMarks.length - 1; // don't count last fake line
|
||
}
|
||
|
||
// Push new token to "stream".
|
||
//
|
||
StateBlock.prototype.push = function (type, tag, nesting) {
|
||
var token = new Token$1(type, tag, nesting);
|
||
token.block = true;
|
||
|
||
if (nesting < 0) this.level--; // closing tag
|
||
token.level = this.level;
|
||
if (nesting > 0) this.level++; // opening tag
|
||
|
||
this.tokens.push(token);
|
||
return token;
|
||
};
|
||
|
||
StateBlock.prototype.isEmpty = function isEmpty(line) {
|
||
return this.bMarks[line] + this.tShift[line] >= this.eMarks[line];
|
||
};
|
||
|
||
StateBlock.prototype.skipEmptyLines = function skipEmptyLines(from) {
|
||
for (var max = this.lineMax; from < max; from++) {
|
||
if (this.bMarks[from] + this.tShift[from] < this.eMarks[from]) {
|
||
break;
|
||
}
|
||
}
|
||
return from;
|
||
};
|
||
|
||
// Skip spaces from given position.
|
||
StateBlock.prototype.skipSpaces = function skipSpaces(pos) {
|
||
var ch;
|
||
|
||
for (var max = this.src.length; pos < max; pos++) {
|
||
ch = this.src.charCodeAt(pos);
|
||
if (!isSpace$4(ch)) { break; }
|
||
}
|
||
return pos;
|
||
};
|
||
|
||
// Skip spaces from given position in reverse.
|
||
StateBlock.prototype.skipSpacesBack = function skipSpacesBack(pos, min) {
|
||
if (pos <= min) { return pos; }
|
||
|
||
while (pos > min) {
|
||
if (!isSpace$4(this.src.charCodeAt(--pos))) { return pos + 1; }
|
||
}
|
||
return pos;
|
||
};
|
||
|
||
// Skip char codes from given position
|
||
StateBlock.prototype.skipChars = function skipChars(pos, code) {
|
||
for (var max = this.src.length; pos < max; pos++) {
|
||
if (this.src.charCodeAt(pos) !== code) { break; }
|
||
}
|
||
return pos;
|
||
};
|
||
|
||
// Skip char codes reverse from given position - 1
|
||
StateBlock.prototype.skipCharsBack = function skipCharsBack(pos, code, min) {
|
||
if (pos <= min) { return pos; }
|
||
|
||
while (pos > min) {
|
||
if (code !== this.src.charCodeAt(--pos)) { return pos + 1; }
|
||
}
|
||
return pos;
|
||
};
|
||
|
||
// cut lines range from source.
|
||
StateBlock.prototype.getLines = function getLines(begin, end, indent, keepLastLF) {
|
||
var i, lineIndent, ch, first, last, queue, lineStart,
|
||
line = begin;
|
||
|
||
if (begin >= end) {
|
||
return '';
|
||
}
|
||
|
||
queue = new Array(end - begin);
|
||
|
||
for (i = 0; line < end; line++, i++) {
|
||
lineIndent = 0;
|
||
lineStart = first = this.bMarks[line];
|
||
|
||
if (line + 1 < end || keepLastLF) {
|
||
// No need for bounds check because we have fake entry on tail.
|
||
last = this.eMarks[line] + 1;
|
||
} else {
|
||
last = this.eMarks[line];
|
||
}
|
||
|
||
while (first < last && lineIndent < indent) {
|
||
ch = this.src.charCodeAt(first);
|
||
|
||
if (isSpace$4(ch)) {
|
||
if (ch === 0x09) {
|
||
lineIndent += 4 - (lineIndent + this.bsCount[line]) % 4;
|
||
} else {
|
||
lineIndent++;
|
||
}
|
||
} else if (first - lineStart < this.tShift[line]) {
|
||
// patched tShift masked characters to look like spaces (blockquotes, list markers)
|
||
lineIndent++;
|
||
} else {
|
||
break;
|
||
}
|
||
|
||
first++;
|
||
}
|
||
|
||
if (lineIndent > indent) {
|
||
// partially expanding tabs in code blocks, e.g '\t\tfoobar'
|
||
// with indent=2 becomes ' \tfoobar'
|
||
queue[i] = new Array(lineIndent - indent + 1).join(' ') + this.src.slice(first, last);
|
||
} else {
|
||
queue[i] = this.src.slice(first, last);
|
||
}
|
||
}
|
||
|
||
return queue.join('');
|
||
};
|
||
|
||
// re-export Token class to use in block rules
|
||
StateBlock.prototype.Token = Token$1;
|
||
|
||
|
||
var state_block = StateBlock;
|
||
|
||
/** internal
|
||
* class ParserBlock
|
||
*
|
||
* Block-level tokenizer.
|
||
**/
|
||
|
||
|
||
var Ruler$1 = ruler;
|
||
|
||
|
||
var _rules$1 = [
|
||
// First 2 params - rule name & source. Secondary array - list of rules,
|
||
// which can be terminated by this one.
|
||
[ 'table', table, [ 'paragraph', 'reference' ] ],
|
||
[ 'code', code ],
|
||
[ 'fence', fence, [ 'paragraph', 'reference', 'blockquote', 'list' ] ],
|
||
[ 'blockquote', blockquote, [ 'paragraph', 'reference', 'blockquote', 'list' ] ],
|
||
[ 'hr', hr, [ 'paragraph', 'reference', 'blockquote', 'list' ] ],
|
||
[ 'list', list, [ 'paragraph', 'reference', 'blockquote' ] ],
|
||
[ 'reference', reference ],
|
||
[ 'html_block', html_block, [ 'paragraph', 'reference', 'blockquote' ] ],
|
||
[ 'heading', heading, [ 'paragraph', 'reference', 'blockquote' ] ],
|
||
[ 'lheading', lheading ],
|
||
[ 'paragraph', paragraph ]
|
||
];
|
||
|
||
|
||
/**
|
||
* new ParserBlock()
|
||
**/
|
||
function ParserBlock$1() {
|
||
/**
|
||
* ParserBlock#ruler -> Ruler
|
||
*
|
||
* [[Ruler]] instance. Keep configuration of block rules.
|
||
**/
|
||
this.ruler = new Ruler$1();
|
||
|
||
for (var i = 0; i < _rules$1.length; i++) {
|
||
this.ruler.push(_rules$1[i][0], _rules$1[i][1], { alt: (_rules$1[i][2] || []).slice() });
|
||
}
|
||
}
|
||
|
||
|
||
// Generate tokens for input range
|
||
//
|
||
ParserBlock$1.prototype.tokenize = function (state, startLine, endLine) {
|
||
var ok, i,
|
||
rules = this.ruler.getRules(''),
|
||
len = rules.length,
|
||
line = startLine,
|
||
hasEmptyLines = false,
|
||
maxNesting = state.md.options.maxNesting;
|
||
|
||
while (line < endLine) {
|
||
state.line = line = state.skipEmptyLines(line);
|
||
if (line >= endLine) { break; }
|
||
|
||
// Termination condition for nested calls.
|
||
// Nested calls currently used for blockquotes & lists
|
||
if (state.sCount[line] < state.blkIndent) { break; }
|
||
|
||
// If nesting level exceeded - skip tail to the end. That's not ordinary
|
||
// situation and we should not care about content.
|
||
if (state.level >= maxNesting) {
|
||
state.line = endLine;
|
||
break;
|
||
}
|
||
|
||
// Try all possible rules.
|
||
// On success, rule should:
|
||
//
|
||
// - update `state.line`
|
||
// - update `state.tokens`
|
||
// - return true
|
||
|
||
for (i = 0; i < len; i++) {
|
||
ok = rules[i](state, line, endLine, false);
|
||
if (ok) { break; }
|
||
}
|
||
|
||
// set state.tight if we had an empty line before current tag
|
||
// i.e. latest empty line should not count
|
||
state.tight = !hasEmptyLines;
|
||
|
||
// paragraph might "eat" one newline after it in nested lists
|
||
if (state.isEmpty(state.line - 1)) {
|
||
hasEmptyLines = true;
|
||
}
|
||
|
||
line = state.line;
|
||
|
||
if (line < endLine && state.isEmpty(line)) {
|
||
hasEmptyLines = true;
|
||
line++;
|
||
state.line = line;
|
||
}
|
||
}
|
||
};
|
||
|
||
|
||
/**
|
||
* ParserBlock.parse(str, md, env, outTokens)
|
||
*
|
||
* Process input string and push block tokens into `outTokens`
|
||
**/
|
||
ParserBlock$1.prototype.parse = function (src, md, env, outTokens) {
|
||
var state;
|
||
|
||
if (!src) { return; }
|
||
|
||
state = new this.State(src, md, env, outTokens);
|
||
|
||
this.tokenize(state, state.line, state.lineMax);
|
||
};
|
||
|
||
|
||
ParserBlock$1.prototype.State = state_block;
|
||
|
||
|
||
var parser_block = ParserBlock$1;
|
||
|
||
// Rule to skip pure text
|
||
// '{}$%@~+=:' reserved for extentions
|
||
|
||
// !, ", #, $, %, &, ', (, ), *, +, ,, -, ., /, :, ;, <, =, >, ?, @, [, \, ], ^, _, `, {, |, }, or ~
|
||
|
||
// !!!! Don't confuse with "Markdown ASCII Punctuation" chars
|
||
// http://spec.commonmark.org/0.15/#ascii-punctuation-character
|
||
function isTerminatorChar(ch) {
|
||
switch (ch) {
|
||
case 0x0A/* \n */:
|
||
case 0x21/* ! */:
|
||
case 0x23/* # */:
|
||
case 0x24/* $ */:
|
||
case 0x25/* % */:
|
||
case 0x26/* & */:
|
||
case 0x2A/* * */:
|
||
case 0x2B/* + */:
|
||
case 0x2D/* - */:
|
||
case 0x3A/* : */:
|
||
case 0x3C/* < */:
|
||
case 0x3D/* = */:
|
||
case 0x3E/* > */:
|
||
case 0x40/* @ */:
|
||
case 0x5B/* [ */:
|
||
case 0x5C/* \ */:
|
||
case 0x5D/* ] */:
|
||
case 0x5E/* ^ */:
|
||
case 0x5F/* _ */:
|
||
case 0x60/* ` */:
|
||
case 0x7B/* { */:
|
||
case 0x7D/* } */:
|
||
case 0x7E/* ~ */:
|
||
return true;
|
||
default:
|
||
return false;
|
||
}
|
||
}
|
||
|
||
var text = function text(state, silent) {
|
||
var pos = state.pos;
|
||
|
||
while (pos < state.posMax && !isTerminatorChar(state.src.charCodeAt(pos))) {
|
||
pos++;
|
||
}
|
||
|
||
if (pos === state.pos) { return false; }
|
||
|
||
if (!silent) { state.pending += state.src.slice(state.pos, pos); }
|
||
|
||
state.pos = pos;
|
||
|
||
return true;
|
||
};
|
||
|
||
var isSpace$3 = utils$1.isSpace;
|
||
|
||
|
||
var newline = function newline(state, silent) {
|
||
var pmax, max, ws, pos = state.pos;
|
||
|
||
if (state.src.charCodeAt(pos) !== 0x0A/* \n */) { return false; }
|
||
|
||
pmax = state.pending.length - 1;
|
||
max = state.posMax;
|
||
|
||
// ' \n' -> hardbreak
|
||
// Lookup in pending chars is bad practice! Don't copy to other rules!
|
||
// Pending string is stored in concat mode, indexed lookups will cause
|
||
// convertion to flat mode.
|
||
if (!silent) {
|
||
if (pmax >= 0 && state.pending.charCodeAt(pmax) === 0x20) {
|
||
if (pmax >= 1 && state.pending.charCodeAt(pmax - 1) === 0x20) {
|
||
// Find whitespaces tail of pending chars.
|
||
ws = pmax - 1;
|
||
while (ws >= 1 && state.pending.charCodeAt(ws - 1) === 0x20) ws--;
|
||
|
||
state.pending = state.pending.slice(0, ws);
|
||
state.push('hardbreak', 'br', 0);
|
||
} else {
|
||
state.pending = state.pending.slice(0, -1);
|
||
state.push('softbreak', 'br', 0);
|
||
}
|
||
|
||
} else {
|
||
state.push('softbreak', 'br', 0);
|
||
}
|
||
}
|
||
|
||
pos++;
|
||
|
||
// skip heading spaces for next line
|
||
while (pos < max && isSpace$3(state.src.charCodeAt(pos))) { pos++; }
|
||
|
||
state.pos = pos;
|
||
return true;
|
||
};
|
||
|
||
var isSpace$2 = utils$1.isSpace;
|
||
|
||
var ESCAPED = [];
|
||
|
||
for (var i = 0; i < 256; i++) { ESCAPED.push(0); }
|
||
|
||
'\\!"#$%&\'()*+,./:;<=>?@[]^_`{|}~-'
|
||
.split('').forEach(function (ch) { ESCAPED[ch.charCodeAt(0)] = 1; });
|
||
|
||
|
||
var _escape = function escape(state, silent) {
|
||
var ch, pos = state.pos, max = state.posMax;
|
||
|
||
if (state.src.charCodeAt(pos) !== 0x5C/* \ */) { return false; }
|
||
|
||
pos++;
|
||
|
||
if (pos < max) {
|
||
ch = state.src.charCodeAt(pos);
|
||
|
||
if (ch < 256 && ESCAPED[ch] !== 0) {
|
||
if (!silent) { state.pending += state.src[pos]; }
|
||
state.pos += 2;
|
||
return true;
|
||
}
|
||
|
||
if (ch === 0x0A) {
|
||
if (!silent) {
|
||
state.push('hardbreak', 'br', 0);
|
||
}
|
||
|
||
pos++;
|
||
// skip leading whitespaces from next line
|
||
while (pos < max) {
|
||
ch = state.src.charCodeAt(pos);
|
||
if (!isSpace$2(ch)) { break; }
|
||
pos++;
|
||
}
|
||
|
||
state.pos = pos;
|
||
return true;
|
||
}
|
||
}
|
||
|
||
if (!silent) { state.pending += '\\'; }
|
||
state.pos++;
|
||
return true;
|
||
};
|
||
|
||
var backticks = function backtick(state, silent) {
|
||
var start, max, marker, token, matchStart, matchEnd, openerLength, closerLength,
|
||
pos = state.pos,
|
||
ch = state.src.charCodeAt(pos);
|
||
|
||
if (ch !== 0x60/* ` */) { return false; }
|
||
|
||
start = pos;
|
||
pos++;
|
||
max = state.posMax;
|
||
|
||
// scan marker length
|
||
while (pos < max && state.src.charCodeAt(pos) === 0x60/* ` */) { pos++; }
|
||
|
||
marker = state.src.slice(start, pos);
|
||
openerLength = marker.length;
|
||
|
||
if (state.backticksScanned && (state.backticks[openerLength] || 0) <= start) {
|
||
if (!silent) state.pending += marker;
|
||
state.pos += openerLength;
|
||
return true;
|
||
}
|
||
|
||
matchStart = matchEnd = pos;
|
||
|
||
// Nothing found in the cache, scan until the end of the line (or until marker is found)
|
||
while ((matchStart = state.src.indexOf('`', matchEnd)) !== -1) {
|
||
matchEnd = matchStart + 1;
|
||
|
||
// scan marker length
|
||
while (matchEnd < max && state.src.charCodeAt(matchEnd) === 0x60/* ` */) { matchEnd++; }
|
||
|
||
closerLength = matchEnd - matchStart;
|
||
|
||
if (closerLength === openerLength) {
|
||
// Found matching closer length.
|
||
if (!silent) {
|
||
token = state.push('code_inline', 'code', 0);
|
||
token.markup = marker;
|
||
token.content = state.src.slice(pos, matchStart)
|
||
.replace(/\n/g, ' ')
|
||
.replace(/^ (.+) $/, '$1');
|
||
}
|
||
state.pos = matchEnd;
|
||
return true;
|
||
}
|
||
|
||
// Some different length found, put it in cache as upper limit of where closer can be found
|
||
state.backticks[closerLength] = matchStart;
|
||
}
|
||
|
||
// Scanned through the end, didn't find anything
|
||
state.backticksScanned = true;
|
||
|
||
if (!silent) state.pending += marker;
|
||
state.pos += openerLength;
|
||
return true;
|
||
};
|
||
|
||
var strikethrough = {};
|
||
|
||
// Insert each marker as a separate text token, and add it to delimiter list
|
||
//
|
||
strikethrough.tokenize = function strikethrough(state, silent) {
|
||
var i, scanned, token, len, ch,
|
||
start = state.pos,
|
||
marker = state.src.charCodeAt(start);
|
||
|
||
if (silent) { return false; }
|
||
|
||
if (marker !== 0x7E/* ~ */) { return false; }
|
||
|
||
scanned = state.scanDelims(state.pos, true);
|
||
len = scanned.length;
|
||
ch = String.fromCharCode(marker);
|
||
|
||
if (len < 2) { return false; }
|
||
|
||
if (len % 2) {
|
||
token = state.push('text', '', 0);
|
||
token.content = ch;
|
||
len--;
|
||
}
|
||
|
||
for (i = 0; i < len; i += 2) {
|
||
token = state.push('text', '', 0);
|
||
token.content = ch + ch;
|
||
|
||
state.delimiters.push({
|
||
marker: marker,
|
||
length: 0, // disable "rule of 3" length checks meant for emphasis
|
||
token: state.tokens.length - 1,
|
||
end: -1,
|
||
open: scanned.can_open,
|
||
close: scanned.can_close
|
||
});
|
||
}
|
||
|
||
state.pos += scanned.length;
|
||
|
||
return true;
|
||
};
|
||
|
||
|
||
function postProcess$1(state, delimiters) {
|
||
var i, j,
|
||
startDelim,
|
||
endDelim,
|
||
token,
|
||
loneMarkers = [],
|
||
max = delimiters.length;
|
||
|
||
for (i = 0; i < max; i++) {
|
||
startDelim = delimiters[i];
|
||
|
||
if (startDelim.marker !== 0x7E/* ~ */) {
|
||
continue;
|
||
}
|
||
|
||
if (startDelim.end === -1) {
|
||
continue;
|
||
}
|
||
|
||
endDelim = delimiters[startDelim.end];
|
||
|
||
token = state.tokens[startDelim.token];
|
||
token.type = 's_open';
|
||
token.tag = 's';
|
||
token.nesting = 1;
|
||
token.markup = '~~';
|
||
token.content = '';
|
||
|
||
token = state.tokens[endDelim.token];
|
||
token.type = 's_close';
|
||
token.tag = 's';
|
||
token.nesting = -1;
|
||
token.markup = '~~';
|
||
token.content = '';
|
||
|
||
if (state.tokens[endDelim.token - 1].type === 'text' &&
|
||
state.tokens[endDelim.token - 1].content === '~') {
|
||
|
||
loneMarkers.push(endDelim.token - 1);
|
||
}
|
||
}
|
||
|
||
// If a marker sequence has an odd number of characters, it's splitted
|
||
// like this: `~~~~~` -> `~` + `~~` + `~~`, leaving one marker at the
|
||
// start of the sequence.
|
||
//
|
||
// So, we have to move all those markers after subsequent s_close tags.
|
||
//
|
||
while (loneMarkers.length) {
|
||
i = loneMarkers.pop();
|
||
j = i + 1;
|
||
|
||
while (j < state.tokens.length && state.tokens[j].type === 's_close') {
|
||
j++;
|
||
}
|
||
|
||
j--;
|
||
|
||
if (i !== j) {
|
||
token = state.tokens[j];
|
||
state.tokens[j] = state.tokens[i];
|
||
state.tokens[i] = token;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
// Walk through delimiter list and replace text tokens with tags
|
||
//
|
||
strikethrough.postProcess = function strikethrough(state) {
|
||
var curr,
|
||
tokens_meta = state.tokens_meta,
|
||
max = state.tokens_meta.length;
|
||
|
||
postProcess$1(state, state.delimiters);
|
||
|
||
for (curr = 0; curr < max; curr++) {
|
||
if (tokens_meta[curr] && tokens_meta[curr].delimiters) {
|
||
postProcess$1(state, tokens_meta[curr].delimiters);
|
||
}
|
||
}
|
||
};
|
||
|
||
var emphasis = {};
|
||
|
||
// Insert each marker as a separate text token, and add it to delimiter list
|
||
//
|
||
emphasis.tokenize = function emphasis(state, silent) {
|
||
var i, scanned, token,
|
||
start = state.pos,
|
||
marker = state.src.charCodeAt(start);
|
||
|
||
if (silent) { return false; }
|
||
|
||
if (marker !== 0x5F /* _ */ && marker !== 0x2A /* * */) { return false; }
|
||
|
||
scanned = state.scanDelims(state.pos, marker === 0x2A);
|
||
|
||
for (i = 0; i < scanned.length; i++) {
|
||
token = state.push('text', '', 0);
|
||
token.content = String.fromCharCode(marker);
|
||
|
||
state.delimiters.push({
|
||
// Char code of the starting marker (number).
|
||
//
|
||
marker: marker,
|
||
|
||
// Total length of these series of delimiters.
|
||
//
|
||
length: scanned.length,
|
||
|
||
// A position of the token this delimiter corresponds to.
|
||
//
|
||
token: state.tokens.length - 1,
|
||
|
||
// If this delimiter is matched as a valid opener, `end` will be
|
||
// equal to its position, otherwise it's `-1`.
|
||
//
|
||
end: -1,
|
||
|
||
// Boolean flags that determine if this delimiter could open or close
|
||
// an emphasis.
|
||
//
|
||
open: scanned.can_open,
|
||
close: scanned.can_close
|
||
});
|
||
}
|
||
|
||
state.pos += scanned.length;
|
||
|
||
return true;
|
||
};
|
||
|
||
|
||
function postProcess(state, delimiters) {
|
||
var i,
|
||
startDelim,
|
||
endDelim,
|
||
token,
|
||
ch,
|
||
isStrong,
|
||
max = delimiters.length;
|
||
|
||
for (i = max - 1; i >= 0; i--) {
|
||
startDelim = delimiters[i];
|
||
|
||
if (startDelim.marker !== 0x5F/* _ */ && startDelim.marker !== 0x2A/* * */) {
|
||
continue;
|
||
}
|
||
|
||
// Process only opening markers
|
||
if (startDelim.end === -1) {
|
||
continue;
|
||
}
|
||
|
||
endDelim = delimiters[startDelim.end];
|
||
|
||
// If the previous delimiter has the same marker and is adjacent to this one,
|
||
// merge those into one strong delimiter.
|
||
//
|
||
// `<em><em>whatever</em></em>` -> `<strong>whatever</strong>`
|
||
//
|
||
isStrong = i > 0 &&
|
||
delimiters[i - 1].end === startDelim.end + 1 &&
|
||
// check that first two markers match and adjacent
|
||
delimiters[i - 1].marker === startDelim.marker &&
|
||
delimiters[i - 1].token === startDelim.token - 1 &&
|
||
// check that last two markers are adjacent (we can safely assume they match)
|
||
delimiters[startDelim.end + 1].token === endDelim.token + 1;
|
||
|
||
ch = String.fromCharCode(startDelim.marker);
|
||
|
||
token = state.tokens[startDelim.token];
|
||
token.type = isStrong ? 'strong_open' : 'em_open';
|
||
token.tag = isStrong ? 'strong' : 'em';
|
||
token.nesting = 1;
|
||
token.markup = isStrong ? ch + ch : ch;
|
||
token.content = '';
|
||
|
||
token = state.tokens[endDelim.token];
|
||
token.type = isStrong ? 'strong_close' : 'em_close';
|
||
token.tag = isStrong ? 'strong' : 'em';
|
||
token.nesting = -1;
|
||
token.markup = isStrong ? ch + ch : ch;
|
||
token.content = '';
|
||
|
||
if (isStrong) {
|
||
state.tokens[delimiters[i - 1].token].content = '';
|
||
state.tokens[delimiters[startDelim.end + 1].token].content = '';
|
||
i--;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
// Walk through delimiter list and replace text tokens with tags
|
||
//
|
||
emphasis.postProcess = function emphasis(state) {
|
||
var curr,
|
||
tokens_meta = state.tokens_meta,
|
||
max = state.tokens_meta.length;
|
||
|
||
postProcess(state, state.delimiters);
|
||
|
||
for (curr = 0; curr < max; curr++) {
|
||
if (tokens_meta[curr] && tokens_meta[curr].delimiters) {
|
||
postProcess(state, tokens_meta[curr].delimiters);
|
||
}
|
||
}
|
||
};
|
||
|
||
var normalizeReference$1 = utils$1.normalizeReference;
|
||
var isSpace$1 = utils$1.isSpace;
|
||
|
||
|
||
var link = function link(state, silent) {
|
||
var attrs,
|
||
code,
|
||
label,
|
||
labelEnd,
|
||
labelStart,
|
||
pos,
|
||
res,
|
||
ref,
|
||
token,
|
||
href = '',
|
||
title = '',
|
||
oldPos = state.pos,
|
||
max = state.posMax,
|
||
start = state.pos,
|
||
parseReference = true;
|
||
|
||
if (state.src.charCodeAt(state.pos) !== 0x5B/* [ */) { return false; }
|
||
|
||
labelStart = state.pos + 1;
|
||
labelEnd = state.md.helpers.parseLinkLabel(state, state.pos, true);
|
||
|
||
// parser failed to find ']', so it's not a valid link
|
||
if (labelEnd < 0) { return false; }
|
||
|
||
pos = labelEnd + 1;
|
||
if (pos < max && state.src.charCodeAt(pos) === 0x28/* ( */) {
|
||
//
|
||
// Inline link
|
||
//
|
||
|
||
// might have found a valid shortcut link, disable reference parsing
|
||
parseReference = false;
|
||
|
||
// [link]( <href> "title" )
|
||
// ^^ skipping these spaces
|
||
pos++;
|
||
for (; pos < max; pos++) {
|
||
code = state.src.charCodeAt(pos);
|
||
if (!isSpace$1(code) && code !== 0x0A) { break; }
|
||
}
|
||
if (pos >= max) { return false; }
|
||
|
||
// [link]( <href> "title" )
|
||
// ^^^^^^ parsing link destination
|
||
start = pos;
|
||
res = state.md.helpers.parseLinkDestination(state.src, pos, state.posMax);
|
||
if (res.ok) {
|
||
href = state.md.normalizeLink(res.str);
|
||
if (state.md.validateLink(href)) {
|
||
pos = res.pos;
|
||
} else {
|
||
href = '';
|
||
}
|
||
|
||
// [link]( <href> "title" )
|
||
// ^^ skipping these spaces
|
||
start = pos;
|
||
for (; pos < max; pos++) {
|
||
code = state.src.charCodeAt(pos);
|
||
if (!isSpace$1(code) && code !== 0x0A) { break; }
|
||
}
|
||
|
||
// [link]( <href> "title" )
|
||
// ^^^^^^^ parsing link title
|
||
res = state.md.helpers.parseLinkTitle(state.src, pos, state.posMax);
|
||
if (pos < max && start !== pos && res.ok) {
|
||
title = res.str;
|
||
pos = res.pos;
|
||
|
||
// [link]( <href> "title" )
|
||
// ^^ skipping these spaces
|
||
for (; pos < max; pos++) {
|
||
code = state.src.charCodeAt(pos);
|
||
if (!isSpace$1(code) && code !== 0x0A) { break; }
|
||
}
|
||
}
|
||
}
|
||
|
||
if (pos >= max || state.src.charCodeAt(pos) !== 0x29/* ) */) {
|
||
// parsing a valid shortcut link failed, fallback to reference
|
||
parseReference = true;
|
||
}
|
||
pos++;
|
||
}
|
||
|
||
if (parseReference) {
|
||
//
|
||
// Link reference
|
||
//
|
||
if (typeof state.env.references === 'undefined') { return false; }
|
||
|
||
if (pos < max && state.src.charCodeAt(pos) === 0x5B/* [ */) {
|
||
start = pos + 1;
|
||
pos = state.md.helpers.parseLinkLabel(state, pos);
|
||
if (pos >= 0) {
|
||
label = state.src.slice(start, pos++);
|
||
} else {
|
||
pos = labelEnd + 1;
|
||
}
|
||
} else {
|
||
pos = labelEnd + 1;
|
||
}
|
||
|
||
// covers label === '' and label === undefined
|
||
// (collapsed reference link and shortcut reference link respectively)
|
||
if (!label) { label = state.src.slice(labelStart, labelEnd); }
|
||
|
||
ref = state.env.references[normalizeReference$1(label)];
|
||
if (!ref) {
|
||
state.pos = oldPos;
|
||
return false;
|
||
}
|
||
href = ref.href;
|
||
title = ref.title;
|
||
}
|
||
|
||
//
|
||
// We found the end of the link, and know for a fact it's a valid link;
|
||
// so all that's left to do is to call tokenizer.
|
||
//
|
||
if (!silent) {
|
||
state.pos = labelStart;
|
||
state.posMax = labelEnd;
|
||
|
||
token = state.push('link_open', 'a', 1);
|
||
token.attrs = attrs = [ [ 'href', href ] ];
|
||
if (title) {
|
||
attrs.push([ 'title', title ]);
|
||
}
|
||
|
||
state.md.inline.tokenize(state);
|
||
|
||
token = state.push('link_close', 'a', -1);
|
||
}
|
||
|
||
state.pos = pos;
|
||
state.posMax = max;
|
||
return true;
|
||
};
|
||
|
||
var normalizeReference = utils$1.normalizeReference;
|
||
var isSpace = utils$1.isSpace;
|
||
|
||
|
||
var image = function image(state, silent) {
|
||
var attrs,
|
||
code,
|
||
content,
|
||
label,
|
||
labelEnd,
|
||
labelStart,
|
||
pos,
|
||
ref,
|
||
res,
|
||
title,
|
||
token,
|
||
tokens,
|
||
start,
|
||
href = '',
|
||
oldPos = state.pos,
|
||
max = state.posMax;
|
||
|
||
if (state.src.charCodeAt(state.pos) !== 0x21/* ! */) { return false; }
|
||
if (state.src.charCodeAt(state.pos + 1) !== 0x5B/* [ */) { return false; }
|
||
|
||
labelStart = state.pos + 2;
|
||
labelEnd = state.md.helpers.parseLinkLabel(state, state.pos + 1, false);
|
||
|
||
// parser failed to find ']', so it's not a valid link
|
||
if (labelEnd < 0) { return false; }
|
||
|
||
pos = labelEnd + 1;
|
||
if (pos < max && state.src.charCodeAt(pos) === 0x28/* ( */) {
|
||
//
|
||
// Inline link
|
||
//
|
||
|
||
// [link]( <href> "title" )
|
||
// ^^ skipping these spaces
|
||
pos++;
|
||
for (; pos < max; pos++) {
|
||
code = state.src.charCodeAt(pos);
|
||
if (!isSpace(code) && code !== 0x0A) { break; }
|
||
}
|
||
if (pos >= max) { return false; }
|
||
|
||
// [link]( <href> "title" )
|
||
// ^^^^^^ parsing link destination
|
||
start = pos;
|
||
res = state.md.helpers.parseLinkDestination(state.src, pos, state.posMax);
|
||
if (res.ok) {
|
||
href = state.md.normalizeLink(res.str);
|
||
if (state.md.validateLink(href)) {
|
||
pos = res.pos;
|
||
} else {
|
||
href = '';
|
||
}
|
||
}
|
||
|
||
// [link]( <href> "title" )
|
||
// ^^ skipping these spaces
|
||
start = pos;
|
||
for (; pos < max; pos++) {
|
||
code = state.src.charCodeAt(pos);
|
||
if (!isSpace(code) && code !== 0x0A) { break; }
|
||
}
|
||
|
||
// [link]( <href> "title" )
|
||
// ^^^^^^^ parsing link title
|
||
res = state.md.helpers.parseLinkTitle(state.src, pos, state.posMax);
|
||
if (pos < max && start !== pos && res.ok) {
|
||
title = res.str;
|
||
pos = res.pos;
|
||
|
||
// [link]( <href> "title" )
|
||
// ^^ skipping these spaces
|
||
for (; pos < max; pos++) {
|
||
code = state.src.charCodeAt(pos);
|
||
if (!isSpace(code) && code !== 0x0A) { break; }
|
||
}
|
||
} else {
|
||
title = '';
|
||
}
|
||
|
||
if (pos >= max || state.src.charCodeAt(pos) !== 0x29/* ) */) {
|
||
state.pos = oldPos;
|
||
return false;
|
||
}
|
||
pos++;
|
||
} else {
|
||
//
|
||
// Link reference
|
||
//
|
||
if (typeof state.env.references === 'undefined') { return false; }
|
||
|
||
if (pos < max && state.src.charCodeAt(pos) === 0x5B/* [ */) {
|
||
start = pos + 1;
|
||
pos = state.md.helpers.parseLinkLabel(state, pos);
|
||
if (pos >= 0) {
|
||
label = state.src.slice(start, pos++);
|
||
} else {
|
||
pos = labelEnd + 1;
|
||
}
|
||
} else {
|
||
pos = labelEnd + 1;
|
||
}
|
||
|
||
// covers label === '' and label === undefined
|
||
// (collapsed reference link and shortcut reference link respectively)
|
||
if (!label) { label = state.src.slice(labelStart, labelEnd); }
|
||
|
||
ref = state.env.references[normalizeReference(label)];
|
||
if (!ref) {
|
||
state.pos = oldPos;
|
||
return false;
|
||
}
|
||
href = ref.href;
|
||
title = ref.title;
|
||
}
|
||
|
||
//
|
||
// We found the end of the link, and know for a fact it's a valid link;
|
||
// so all that's left to do is to call tokenizer.
|
||
//
|
||
if (!silent) {
|
||
content = state.src.slice(labelStart, labelEnd);
|
||
|
||
state.md.inline.parse(
|
||
content,
|
||
state.md,
|
||
state.env,
|
||
tokens = []
|
||
);
|
||
|
||
token = state.push('image', 'img', 0);
|
||
token.attrs = attrs = [ [ 'src', href ], [ 'alt', '' ] ];
|
||
token.children = tokens;
|
||
token.content = content;
|
||
|
||
if (title) {
|
||
attrs.push([ 'title', title ]);
|
||
}
|
||
}
|
||
|
||
state.pos = pos;
|
||
state.posMax = max;
|
||
return true;
|
||
};
|
||
|
||
/*eslint max-len:0*/
|
||
var EMAIL_RE = /^([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])?)*)$/;
|
||
var AUTOLINK_RE = /^([a-zA-Z][a-zA-Z0-9+.\-]{1,31}):([^<>\x00-\x20]*)$/;
|
||
|
||
|
||
var autolink = function autolink(state, silent) {
|
||
var url, fullUrl, token, ch, start, max,
|
||
pos = state.pos;
|
||
|
||
if (state.src.charCodeAt(pos) !== 0x3C/* < */) { return false; }
|
||
|
||
start = state.pos;
|
||
max = state.posMax;
|
||
|
||
for (;;) {
|
||
if (++pos >= max) return false;
|
||
|
||
ch = state.src.charCodeAt(pos);
|
||
|
||
if (ch === 0x3C /* < */) return false;
|
||
if (ch === 0x3E /* > */) break;
|
||
}
|
||
|
||
url = state.src.slice(start + 1, pos);
|
||
|
||
if (AUTOLINK_RE.test(url)) {
|
||
fullUrl = state.md.normalizeLink(url);
|
||
if (!state.md.validateLink(fullUrl)) { return false; }
|
||
|
||
if (!silent) {
|
||
token = state.push('link_open', 'a', 1);
|
||
token.attrs = [ [ 'href', fullUrl ] ];
|
||
token.markup = 'autolink';
|
||
token.info = 'auto';
|
||
|
||
token = state.push('text', '', 0);
|
||
token.content = state.md.normalizeLinkText(url);
|
||
|
||
token = state.push('link_close', 'a', -1);
|
||
token.markup = 'autolink';
|
||
token.info = 'auto';
|
||
}
|
||
|
||
state.pos += url.length + 2;
|
||
return true;
|
||
}
|
||
|
||
if (EMAIL_RE.test(url)) {
|
||
fullUrl = state.md.normalizeLink('mailto:' + url);
|
||
if (!state.md.validateLink(fullUrl)) { return false; }
|
||
|
||
if (!silent) {
|
||
token = state.push('link_open', 'a', 1);
|
||
token.attrs = [ [ 'href', fullUrl ] ];
|
||
token.markup = 'autolink';
|
||
token.info = 'auto';
|
||
|
||
token = state.push('text', '', 0);
|
||
token.content = state.md.normalizeLinkText(url);
|
||
|
||
token = state.push('link_close', 'a', -1);
|
||
token.markup = 'autolink';
|
||
token.info = 'auto';
|
||
}
|
||
|
||
state.pos += url.length + 2;
|
||
return true;
|
||
}
|
||
|
||
return false;
|
||
};
|
||
|
||
var HTML_TAG_RE = html_re.HTML_TAG_RE;
|
||
|
||
|
||
function isLetter(ch) {
|
||
/*eslint no-bitwise:0*/
|
||
var lc = ch | 0x20; // to lower case
|
||
return (lc >= 0x61/* a */) && (lc <= 0x7a/* z */);
|
||
}
|
||
|
||
|
||
var html_inline = function html_inline(state, silent) {
|
||
var ch, match, max, token,
|
||
pos = state.pos;
|
||
|
||
if (!state.md.options.html) { return false; }
|
||
|
||
// Check start
|
||
max = state.posMax;
|
||
if (state.src.charCodeAt(pos) !== 0x3C/* < */ ||
|
||
pos + 2 >= max) {
|
||
return false;
|
||
}
|
||
|
||
// Quick fail on second char
|
||
ch = state.src.charCodeAt(pos + 1);
|
||
if (ch !== 0x21/* ! */ &&
|
||
ch !== 0x3F/* ? */ &&
|
||
ch !== 0x2F/* / */ &&
|
||
!isLetter(ch)) {
|
||
return false;
|
||
}
|
||
|
||
match = state.src.slice(pos).match(HTML_TAG_RE);
|
||
if (!match) { return false; }
|
||
|
||
if (!silent) {
|
||
token = state.push('html_inline', '', 0);
|
||
token.content = state.src.slice(pos, pos + match[0].length);
|
||
}
|
||
state.pos += match[0].length;
|
||
return true;
|
||
};
|
||
|
||
var entities = entities$1;
|
||
var has = utils$1.has;
|
||
var isValidEntityCode = utils$1.isValidEntityCode;
|
||
var fromCodePoint = utils$1.fromCodePoint;
|
||
|
||
|
||
var DIGITAL_RE = /^&#((?:x[a-f0-9]{1,6}|[0-9]{1,7}));/i;
|
||
var NAMED_RE = /^&([a-z][a-z0-9]{1,31});/i;
|
||
|
||
|
||
var entity = function entity(state, silent) {
|
||
var ch, code, match, pos = state.pos, max = state.posMax;
|
||
|
||
if (state.src.charCodeAt(pos) !== 0x26/* & */) { return false; }
|
||
|
||
if (pos + 1 < max) {
|
||
ch = state.src.charCodeAt(pos + 1);
|
||
|
||
if (ch === 0x23 /* # */) {
|
||
match = state.src.slice(pos).match(DIGITAL_RE);
|
||
if (match) {
|
||
if (!silent) {
|
||
code = match[1][0].toLowerCase() === 'x' ? parseInt(match[1].slice(1), 16) : parseInt(match[1], 10);
|
||
state.pending += isValidEntityCode(code) ? fromCodePoint(code) : fromCodePoint(0xFFFD);
|
||
}
|
||
state.pos += match[0].length;
|
||
return true;
|
||
}
|
||
} else {
|
||
match = state.src.slice(pos).match(NAMED_RE);
|
||
if (match) {
|
||
if (has(entities, match[1])) {
|
||
if (!silent) { state.pending += entities[match[1]]; }
|
||
state.pos += match[0].length;
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!silent) { state.pending += '&'; }
|
||
state.pos++;
|
||
return true;
|
||
};
|
||
|
||
function processDelimiters(state, delimiters) {
|
||
var closerIdx, openerIdx, closer, opener, minOpenerIdx, newMinOpenerIdx,
|
||
isOddMatch, lastJump,
|
||
openersBottom = {},
|
||
max = delimiters.length;
|
||
|
||
if (!max) return;
|
||
|
||
// headerIdx is the first delimiter of the current (where closer is) delimiter run
|
||
var headerIdx = 0;
|
||
var lastTokenIdx = -2; // needs any value lower than -1
|
||
var jumps = [];
|
||
|
||
for (closerIdx = 0; closerIdx < max; closerIdx++) {
|
||
closer = delimiters[closerIdx];
|
||
|
||
jumps.push(0);
|
||
|
||
// markers belong to same delimiter run if:
|
||
// - they have adjacent tokens
|
||
// - AND markers are the same
|
||
//
|
||
if (delimiters[headerIdx].marker !== closer.marker || lastTokenIdx !== closer.token - 1) {
|
||
headerIdx = closerIdx;
|
||
}
|
||
|
||
lastTokenIdx = closer.token;
|
||
|
||
// Length is only used for emphasis-specific "rule of 3",
|
||
// if it's not defined (in strikethrough or 3rd party plugins),
|
||
// we can default it to 0 to disable those checks.
|
||
//
|
||
closer.length = closer.length || 0;
|
||
|
||
if (!closer.close) continue;
|
||
|
||
// Previously calculated lower bounds (previous fails)
|
||
// for each marker, each delimiter length modulo 3,
|
||
// and for whether this closer can be an opener;
|
||
// https://github.com/commonmark/cmark/commit/34250e12ccebdc6372b8b49c44fab57c72443460
|
||
if (!openersBottom.hasOwnProperty(closer.marker)) {
|
||
openersBottom[closer.marker] = [ -1, -1, -1, -1, -1, -1 ];
|
||
}
|
||
|
||
minOpenerIdx = openersBottom[closer.marker][(closer.open ? 3 : 0) + (closer.length % 3)];
|
||
|
||
openerIdx = headerIdx - jumps[headerIdx] - 1;
|
||
|
||
newMinOpenerIdx = openerIdx;
|
||
|
||
for (; openerIdx > minOpenerIdx; openerIdx -= jumps[openerIdx] + 1) {
|
||
opener = delimiters[openerIdx];
|
||
|
||
if (opener.marker !== closer.marker) continue;
|
||
|
||
if (opener.open && opener.end < 0) {
|
||
|
||
isOddMatch = false;
|
||
|
||
// from spec:
|
||
//
|
||
// If one of the delimiters can both open and close emphasis, then the
|
||
// sum of the lengths of the delimiter runs containing the opening and
|
||
// closing delimiters must not be a multiple of 3 unless both lengths
|
||
// are multiples of 3.
|
||
//
|
||
if (opener.close || closer.open) {
|
||
if ((opener.length + closer.length) % 3 === 0) {
|
||
if (opener.length % 3 !== 0 || closer.length % 3 !== 0) {
|
||
isOddMatch = true;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!isOddMatch) {
|
||
// If previous delimiter cannot be an opener, we can safely skip
|
||
// the entire sequence in future checks. This is required to make
|
||
// sure algorithm has linear complexity (see *_*_*_*_*_... case).
|
||
//
|
||
lastJump = openerIdx > 0 && !delimiters[openerIdx - 1].open ?
|
||
jumps[openerIdx - 1] + 1 :
|
||
0;
|
||
|
||
jumps[closerIdx] = closerIdx - openerIdx + lastJump;
|
||
jumps[openerIdx] = lastJump;
|
||
|
||
closer.open = false;
|
||
opener.end = closerIdx;
|
||
opener.close = false;
|
||
newMinOpenerIdx = -1;
|
||
// treat next token as start of run,
|
||
// it optimizes skips in **<...>**a**<...>** pathological case
|
||
lastTokenIdx = -2;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (newMinOpenerIdx !== -1) {
|
||
// If match for this delimiter run failed, we want to set lower bound for
|
||
// future lookups. This is required to make sure algorithm has linear
|
||
// complexity.
|
||
//
|
||
// See details here:
|
||
// https://github.com/commonmark/cmark/issues/178#issuecomment-270417442
|
||
//
|
||
openersBottom[closer.marker][(closer.open ? 3 : 0) + ((closer.length || 0) % 3)] = newMinOpenerIdx;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
var balance_pairs = function link_pairs(state) {
|
||
var curr,
|
||
tokens_meta = state.tokens_meta,
|
||
max = state.tokens_meta.length;
|
||
|
||
processDelimiters(state, state.delimiters);
|
||
|
||
for (curr = 0; curr < max; curr++) {
|
||
if (tokens_meta[curr] && tokens_meta[curr].delimiters) {
|
||
processDelimiters(state, tokens_meta[curr].delimiters);
|
||
}
|
||
}
|
||
};
|
||
|
||
var text_collapse = function text_collapse(state) {
|
||
var curr, last,
|
||
level = 0,
|
||
tokens = state.tokens,
|
||
max = state.tokens.length;
|
||
|
||
for (curr = last = 0; curr < max; curr++) {
|
||
// re-calculate levels after emphasis/strikethrough turns some text nodes
|
||
// into opening/closing tags
|
||
if (tokens[curr].nesting < 0) level--; // closing tag
|
||
tokens[curr].level = level;
|
||
if (tokens[curr].nesting > 0) level++; // opening tag
|
||
|
||
if (tokens[curr].type === 'text' &&
|
||
curr + 1 < max &&
|
||
tokens[curr + 1].type === 'text') {
|
||
|
||
// collapse two adjacent text nodes
|
||
tokens[curr + 1].content = tokens[curr].content + tokens[curr + 1].content;
|
||
} else {
|
||
if (curr !== last) { tokens[last] = tokens[curr]; }
|
||
|
||
last++;
|
||
}
|
||
}
|
||
|
||
if (curr !== last) {
|
||
tokens.length = last;
|
||
}
|
||
};
|
||
|
||
var Token = token;
|
||
var isWhiteSpace = utils$1.isWhiteSpace;
|
||
var isPunctChar = utils$1.isPunctChar;
|
||
var isMdAsciiPunct = utils$1.isMdAsciiPunct;
|
||
|
||
|
||
function StateInline(src, md, env, outTokens) {
|
||
this.src = src;
|
||
this.env = env;
|
||
this.md = md;
|
||
this.tokens = outTokens;
|
||
this.tokens_meta = Array(outTokens.length);
|
||
|
||
this.pos = 0;
|
||
this.posMax = this.src.length;
|
||
this.level = 0;
|
||
this.pending = '';
|
||
this.pendingLevel = 0;
|
||
|
||
// Stores { start: end } pairs. Useful for backtrack
|
||
// optimization of pairs parse (emphasis, strikes).
|
||
this.cache = {};
|
||
|
||
// List of emphasis-like delimiters for current tag
|
||
this.delimiters = [];
|
||
|
||
// Stack of delimiter lists for upper level tags
|
||
this._prev_delimiters = [];
|
||
|
||
// backtick length => last seen position
|
||
this.backticks = {};
|
||
this.backticksScanned = false;
|
||
}
|
||
|
||
|
||
// Flush pending text
|
||
//
|
||
StateInline.prototype.pushPending = function () {
|
||
var token = new Token('text', '', 0);
|
||
token.content = this.pending;
|
||
token.level = this.pendingLevel;
|
||
this.tokens.push(token);
|
||
this.pending = '';
|
||
return token;
|
||
};
|
||
|
||
|
||
// Push new token to "stream".
|
||
// If pending text exists - flush it as text token
|
||
//
|
||
StateInline.prototype.push = function (type, tag, nesting) {
|
||
if (this.pending) {
|
||
this.pushPending();
|
||
}
|
||
|
||
var token = new Token(type, tag, nesting);
|
||
var token_meta = null;
|
||
|
||
if (nesting < 0) {
|
||
// closing tag
|
||
this.level--;
|
||
this.delimiters = this._prev_delimiters.pop();
|
||
}
|
||
|
||
token.level = this.level;
|
||
|
||
if (nesting > 0) {
|
||
// opening tag
|
||
this.level++;
|
||
this._prev_delimiters.push(this.delimiters);
|
||
this.delimiters = [];
|
||
token_meta = { delimiters: this.delimiters };
|
||
}
|
||
|
||
this.pendingLevel = this.level;
|
||
this.tokens.push(token);
|
||
this.tokens_meta.push(token_meta);
|
||
return token;
|
||
};
|
||
|
||
|
||
// Scan a sequence of emphasis-like markers, and determine whether
|
||
// it can start an emphasis sequence or end an emphasis sequence.
|
||
//
|
||
// - start - position to scan from (it should point at a valid marker);
|
||
// - canSplitWord - determine if these markers can be found inside a word
|
||
//
|
||
StateInline.prototype.scanDelims = function (start, canSplitWord) {
|
||
var pos = start, lastChar, nextChar, count, can_open, can_close,
|
||
isLastWhiteSpace, isLastPunctChar,
|
||
isNextWhiteSpace, isNextPunctChar,
|
||
left_flanking = true,
|
||
right_flanking = true,
|
||
max = this.posMax,
|
||
marker = this.src.charCodeAt(start);
|
||
|
||
// treat beginning of the line as a whitespace
|
||
lastChar = start > 0 ? this.src.charCodeAt(start - 1) : 0x20;
|
||
|
||
while (pos < max && this.src.charCodeAt(pos) === marker) { pos++; }
|
||
|
||
count = pos - start;
|
||
|
||
// treat end of the line as a whitespace
|
||
nextChar = pos < max ? this.src.charCodeAt(pos) : 0x20;
|
||
|
||
isLastPunctChar = isMdAsciiPunct(lastChar) || isPunctChar(String.fromCharCode(lastChar));
|
||
isNextPunctChar = isMdAsciiPunct(nextChar) || isPunctChar(String.fromCharCode(nextChar));
|
||
|
||
isLastWhiteSpace = isWhiteSpace(lastChar);
|
||
isNextWhiteSpace = isWhiteSpace(nextChar);
|
||
|
||
if (isNextWhiteSpace) {
|
||
left_flanking = false;
|
||
} else if (isNextPunctChar) {
|
||
if (!(isLastWhiteSpace || isLastPunctChar)) {
|
||
left_flanking = false;
|
||
}
|
||
}
|
||
|
||
if (isLastWhiteSpace) {
|
||
right_flanking = false;
|
||
} else if (isLastPunctChar) {
|
||
if (!(isNextWhiteSpace || isNextPunctChar)) {
|
||
right_flanking = false;
|
||
}
|
||
}
|
||
|
||
if (!canSplitWord) {
|
||
can_open = left_flanking && (!right_flanking || isLastPunctChar);
|
||
can_close = right_flanking && (!left_flanking || isNextPunctChar);
|
||
} else {
|
||
can_open = left_flanking;
|
||
can_close = right_flanking;
|
||
}
|
||
|
||
return {
|
||
can_open: can_open,
|
||
can_close: can_close,
|
||
length: count
|
||
};
|
||
};
|
||
|
||
|
||
// re-export Token class to use in block rules
|
||
StateInline.prototype.Token = Token;
|
||
|
||
|
||
var state_inline = StateInline;
|
||
|
||
/** internal
|
||
* class ParserInline
|
||
*
|
||
* Tokenizes paragraph content.
|
||
**/
|
||
|
||
|
||
var Ruler = ruler;
|
||
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
// Parser rules
|
||
|
||
var _rules = [
|
||
[ 'text', text ],
|
||
[ 'newline', newline ],
|
||
[ 'escape', _escape ],
|
||
[ 'backticks', backticks ],
|
||
[ 'strikethrough', strikethrough.tokenize ],
|
||
[ 'emphasis', emphasis.tokenize ],
|
||
[ 'link', link ],
|
||
[ 'image', image ],
|
||
[ 'autolink', autolink ],
|
||
[ 'html_inline', html_inline ],
|
||
[ 'entity', entity ]
|
||
];
|
||
|
||
var _rules2 = [
|
||
[ 'balance_pairs', balance_pairs ],
|
||
[ 'strikethrough', strikethrough.postProcess ],
|
||
[ 'emphasis', emphasis.postProcess ],
|
||
[ 'text_collapse', text_collapse ]
|
||
];
|
||
|
||
|
||
/**
|
||
* new ParserInline()
|
||
**/
|
||
function ParserInline$1() {
|
||
var i;
|
||
|
||
/**
|
||
* ParserInline#ruler -> Ruler
|
||
*
|
||
* [[Ruler]] instance. Keep configuration of inline rules.
|
||
**/
|
||
this.ruler = new Ruler();
|
||
|
||
for (i = 0; i < _rules.length; i++) {
|
||
this.ruler.push(_rules[i][0], _rules[i][1]);
|
||
}
|
||
|
||
/**
|
||
* ParserInline#ruler2 -> Ruler
|
||
*
|
||
* [[Ruler]] instance. Second ruler used for post-processing
|
||
* (e.g. in emphasis-like rules).
|
||
**/
|
||
this.ruler2 = new Ruler();
|
||
|
||
for (i = 0; i < _rules2.length; i++) {
|
||
this.ruler2.push(_rules2[i][0], _rules2[i][1]);
|
||
}
|
||
}
|
||
|
||
|
||
// Skip single token by running all rules in validation mode;
|
||
// returns `true` if any rule reported success
|
||
//
|
||
ParserInline$1.prototype.skipToken = function (state) {
|
||
var ok, i, pos = state.pos,
|
||
rules = this.ruler.getRules(''),
|
||
len = rules.length,
|
||
maxNesting = state.md.options.maxNesting,
|
||
cache = state.cache;
|
||
|
||
|
||
if (typeof cache[pos] !== 'undefined') {
|
||
state.pos = cache[pos];
|
||
return;
|
||
}
|
||
|
||
if (state.level < maxNesting) {
|
||
for (i = 0; i < len; i++) {
|
||
// Increment state.level and decrement it later to limit recursion.
|
||
// It's harmless to do here, because no tokens are created. But ideally,
|
||
// we'd need a separate private state variable for this purpose.
|
||
//
|
||
state.level++;
|
||
ok = rules[i](state, true);
|
||
state.level--;
|
||
|
||
if (ok) { break; }
|
||
}
|
||
} else {
|
||
// Too much nesting, just skip until the end of the paragraph.
|
||
//
|
||
// NOTE: this will cause links to behave incorrectly in the following case,
|
||
// when an amount of `[` is exactly equal to `maxNesting + 1`:
|
||
//
|
||
// [[[[[[[[[[[[[[[[[[[[[foo]()
|
||
//
|
||
// TODO: remove this workaround when CM standard will allow nested links
|
||
// (we can replace it by preventing links from being parsed in
|
||
// validation mode)
|
||
//
|
||
state.pos = state.posMax;
|
||
}
|
||
|
||
if (!ok) { state.pos++; }
|
||
cache[pos] = state.pos;
|
||
};
|
||
|
||
|
||
// Generate tokens for input range
|
||
//
|
||
ParserInline$1.prototype.tokenize = function (state) {
|
||
var ok, i,
|
||
rules = this.ruler.getRules(''),
|
||
len = rules.length,
|
||
end = state.posMax,
|
||
maxNesting = state.md.options.maxNesting;
|
||
|
||
while (state.pos < end) {
|
||
// Try all possible rules.
|
||
// On success, rule should:
|
||
//
|
||
// - update `state.pos`
|
||
// - update `state.tokens`
|
||
// - return true
|
||
|
||
if (state.level < maxNesting) {
|
||
for (i = 0; i < len; i++) {
|
||
ok = rules[i](state, false);
|
||
if (ok) { break; }
|
||
}
|
||
}
|
||
|
||
if (ok) {
|
||
if (state.pos >= end) { break; }
|
||
continue;
|
||
}
|
||
|
||
state.pending += state.src[state.pos++];
|
||
}
|
||
|
||
if (state.pending) {
|
||
state.pushPending();
|
||
}
|
||
};
|
||
|
||
|
||
/**
|
||
* ParserInline.parse(str, md, env, outTokens)
|
||
*
|
||
* Process input string and push inline tokens into `outTokens`
|
||
**/
|
||
ParserInline$1.prototype.parse = function (str, md, env, outTokens) {
|
||
var i, rules, len;
|
||
var state = new this.State(str, md, env, outTokens);
|
||
|
||
this.tokenize(state);
|
||
|
||
rules = this.ruler2.getRules('');
|
||
len = rules.length;
|
||
|
||
for (i = 0; i < len; i++) {
|
||
rules[i](state);
|
||
}
|
||
};
|
||
|
||
|
||
ParserInline$1.prototype.State = state_inline;
|
||
|
||
|
||
var parser_inline = ParserInline$1;
|
||
|
||
var re = function (opts) {
|
||
var re = {};
|
||
|
||
// Use direct extract instead of `regenerate` to reduse browserified size
|
||
re.src_Any = regex$3.source;
|
||
re.src_Cc = regex$2.source;
|
||
re.src_Z = regex.source;
|
||
re.src_P = regex$4.source;
|
||
|
||
// \p{\Z\P\Cc\CF} (white spaces + control + format + punctuation)
|
||
re.src_ZPCc = [ re.src_Z, re.src_P, re.src_Cc ].join('|');
|
||
|
||
// \p{\Z\Cc} (white spaces + control)
|
||
re.src_ZCc = [ re.src_Z, re.src_Cc ].join('|');
|
||
|
||
// Experimental. List of chars, completely prohibited in links
|
||
// because can separate it from other part of text
|
||
var text_separators = '[><\uff5c]';
|
||
|
||
// All possible word characters (everything without punctuation, spaces & controls)
|
||
// Defined via punctuation & spaces to save space
|
||
// Should be something like \p{\L\N\S\M} (\w but without `_`)
|
||
re.src_pseudo_letter = '(?:(?!' + text_separators + '|' + re.src_ZPCc + ')' + re.src_Any + ')';
|
||
// The same as abothe but without [0-9]
|
||
// var src_pseudo_letter_non_d = '(?:(?![0-9]|' + src_ZPCc + ')' + src_Any + ')';
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
|
||
re.src_ip4 =
|
||
|
||
'(?:(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)';
|
||
|
||
// Prohibit any of "@/[]()" in user/pass to avoid wrong domain fetch.
|
||
re.src_auth = '(?:(?:(?!' + re.src_ZCc + '|[@/\\[\\]()]).)+@)?';
|
||
|
||
re.src_port =
|
||
|
||
'(?::(?:6(?:[0-4]\\d{3}|5(?:[0-4]\\d{2}|5(?:[0-2]\\d|3[0-5])))|[1-5]?\\d{1,4}))?';
|
||
|
||
re.src_host_terminator =
|
||
|
||
'(?=$|' + text_separators + '|' + re.src_ZPCc + ')(?!-|_|:\\d|\\.-|\\.(?!$|' + re.src_ZPCc + '))';
|
||
|
||
re.src_path =
|
||
|
||
'(?:' +
|
||
'[/?#]' +
|
||
'(?:' +
|
||
'(?!' + re.src_ZCc + '|' + text_separators + '|[()[\\]{}.,"\'?!\\-]).|' +
|
||
'\\[(?:(?!' + re.src_ZCc + '|\\]).)*\\]|' +
|
||
'\\((?:(?!' + re.src_ZCc + '|[)]).)*\\)|' +
|
||
'\\{(?:(?!' + re.src_ZCc + '|[}]).)*\\}|' +
|
||
'\\"(?:(?!' + re.src_ZCc + '|["]).)+\\"|' +
|
||
"\\'(?:(?!" + re.src_ZCc + "|[']).)+\\'|" +
|
||
"\\'(?=" + re.src_pseudo_letter + '|[-]).|' + // allow `I'm_king` if no pair found
|
||
'\\.{2,}[a-zA-Z0-9%/&]|' + // google has many dots in "google search" links (#66, #81).
|
||
// github has ... in commit range links,
|
||
// Restrict to
|
||
// - english
|
||
// - percent-encoded
|
||
// - parts of file path
|
||
// - params separator
|
||
// until more examples found.
|
||
'\\.(?!' + re.src_ZCc + '|[.]).|' +
|
||
(opts && opts['---'] ?
|
||
'\\-(?!--(?:[^-]|$))(?:-*)|' // `---` => long dash, terminate
|
||
:
|
||
'\\-+|'
|
||
) +
|
||
'\\,(?!' + re.src_ZCc + ').|' + // allow `,,,` in paths
|
||
'\\!+(?!' + re.src_ZCc + '|[!]).|' + // allow `!!!` in paths, but not at the end
|
||
'\\?(?!' + re.src_ZCc + '|[?]).' +
|
||
')+' +
|
||
'|\\/' +
|
||
')?';
|
||
|
||
// Allow anything in markdown spec, forbid quote (") at the first position
|
||
// because emails enclosed in quotes are far more common
|
||
re.src_email_name =
|
||
|
||
'[\\-;:&=\\+\\$,\\.a-zA-Z0-9_][\\-;:&=\\+\\$,\\"\\.a-zA-Z0-9_]*';
|
||
|
||
re.src_xn =
|
||
|
||
'xn--[a-z0-9\\-]{1,59}';
|
||
|
||
// More to read about domain names
|
||
// http://serverfault.com/questions/638260/
|
||
|
||
re.src_domain_root =
|
||
|
||
// Allow letters & digits (http://test1)
|
||
'(?:' +
|
||
re.src_xn +
|
||
'|' +
|
||
re.src_pseudo_letter + '{1,63}' +
|
||
')';
|
||
|
||
re.src_domain =
|
||
|
||
'(?:' +
|
||
re.src_xn +
|
||
'|' +
|
||
'(?:' + re.src_pseudo_letter + ')' +
|
||
'|' +
|
||
'(?:' + re.src_pseudo_letter + '(?:-|' + re.src_pseudo_letter + '){0,61}' + re.src_pseudo_letter + ')' +
|
||
')';
|
||
|
||
re.src_host =
|
||
|
||
'(?:' +
|
||
// Don't need IP check, because digits are already allowed in normal domain names
|
||
// src_ip4 +
|
||
// '|' +
|
||
'(?:(?:(?:' + re.src_domain + ')\\.)*' + re.src_domain/*_root*/ + ')' +
|
||
')';
|
||
|
||
re.tpl_host_fuzzy =
|
||
|
||
'(?:' +
|
||
re.src_ip4 +
|
||
'|' +
|
||
'(?:(?:(?:' + re.src_domain + ')\\.)+(?:%TLDS%))' +
|
||
')';
|
||
|
||
re.tpl_host_no_ip_fuzzy =
|
||
|
||
'(?:(?:(?:' + re.src_domain + ')\\.)+(?:%TLDS%))';
|
||
|
||
re.src_host_strict =
|
||
|
||
re.src_host + re.src_host_terminator;
|
||
|
||
re.tpl_host_fuzzy_strict =
|
||
|
||
re.tpl_host_fuzzy + re.src_host_terminator;
|
||
|
||
re.src_host_port_strict =
|
||
|
||
re.src_host + re.src_port + re.src_host_terminator;
|
||
|
||
re.tpl_host_port_fuzzy_strict =
|
||
|
||
re.tpl_host_fuzzy + re.src_port + re.src_host_terminator;
|
||
|
||
re.tpl_host_port_no_ip_fuzzy_strict =
|
||
|
||
re.tpl_host_no_ip_fuzzy + re.src_port + re.src_host_terminator;
|
||
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
// Main rules
|
||
|
||
// Rude test fuzzy links by host, for quick deny
|
||
re.tpl_host_fuzzy_test =
|
||
|
||
'localhost|www\\.|\\.\\d{1,3}\\.|(?:\\.(?:%TLDS%)(?:' + re.src_ZPCc + '|>|$))';
|
||
|
||
re.tpl_email_fuzzy =
|
||
|
||
'(^|' + text_separators + '|"|\\(|' + re.src_ZCc + ')' +
|
||
'(' + re.src_email_name + '@' + re.tpl_host_fuzzy_strict + ')';
|
||
|
||
re.tpl_link_fuzzy =
|
||
// Fuzzy link can't be prepended with .:/\- and non punctuation.
|
||
// but can start with > (markdown blockquote)
|
||
'(^|(?![.:/\\-_@])(?:[$+<=>^`|\uff5c]|' + re.src_ZPCc + '))' +
|
||
'((?![$+<=>^`|\uff5c])' + re.tpl_host_port_fuzzy_strict + re.src_path + ')';
|
||
|
||
re.tpl_link_no_ip_fuzzy =
|
||
// Fuzzy link can't be prepended with .:/\- and non punctuation.
|
||
// but can start with > (markdown blockquote)
|
||
'(^|(?![.:/\\-_@])(?:[$+<=>^`|\uff5c]|' + re.src_ZPCc + '))' +
|
||
'((?![$+<=>^`|\uff5c])' + re.tpl_host_port_no_ip_fuzzy_strict + re.src_path + ')';
|
||
|
||
return re;
|
||
};
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
// Helpers
|
||
|
||
// Merge objects
|
||
//
|
||
function assign(obj /*from1, from2, from3, ...*/) {
|
||
var sources = Array.prototype.slice.call(arguments, 1);
|
||
|
||
sources.forEach(function (source) {
|
||
if (!source) { return; }
|
||
|
||
Object.keys(source).forEach(function (key) {
|
||
obj[key] = source[key];
|
||
});
|
||
});
|
||
|
||
return obj;
|
||
}
|
||
|
||
function _class(obj) { return Object.prototype.toString.call(obj); }
|
||
function isString(obj) { return _class(obj) === '[object String]'; }
|
||
function isObject(obj) { return _class(obj) === '[object Object]'; }
|
||
function isRegExp(obj) { return _class(obj) === '[object RegExp]'; }
|
||
function isFunction(obj) { return _class(obj) === '[object Function]'; }
|
||
|
||
|
||
function escapeRE(str) { return str.replace(/[.?*+^$[\]\\(){}|-]/g, '\\$&'); }
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
var defaultOptions = {
|
||
fuzzyLink: true,
|
||
fuzzyEmail: true,
|
||
fuzzyIP: false
|
||
};
|
||
|
||
|
||
function isOptionsObj(obj) {
|
||
return Object.keys(obj || {}).reduce(function (acc, k) {
|
||
return acc || defaultOptions.hasOwnProperty(k);
|
||
}, false);
|
||
}
|
||
|
||
|
||
var defaultSchemas = {
|
||
'http:': {
|
||
validate: function (text, pos, self) {
|
||
var tail = text.slice(pos);
|
||
|
||
if (!self.re.http) {
|
||
// compile lazily, because "host"-containing variables can change on tlds update.
|
||
self.re.http = new RegExp(
|
||
'^\\/\\/' + self.re.src_auth + self.re.src_host_port_strict + self.re.src_path, 'i'
|
||
);
|
||
}
|
||
if (self.re.http.test(tail)) {
|
||
return tail.match(self.re.http)[0].length;
|
||
}
|
||
return 0;
|
||
}
|
||
},
|
||
'https:': 'http:',
|
||
'ftp:': 'http:',
|
||
'//': {
|
||
validate: function (text, pos, self) {
|
||
var tail = text.slice(pos);
|
||
|
||
if (!self.re.no_http) {
|
||
// compile lazily, because "host"-containing variables can change on tlds update.
|
||
self.re.no_http = new RegExp(
|
||
'^' +
|
||
self.re.src_auth +
|
||
// Don't allow single-level domains, because of false positives like '//test'
|
||
// with code comments
|
||
'(?:localhost|(?:(?:' + self.re.src_domain + ')\\.)+' + self.re.src_domain_root + ')' +
|
||
self.re.src_port +
|
||
self.re.src_host_terminator +
|
||
self.re.src_path,
|
||
|
||
'i'
|
||
);
|
||
}
|
||
|
||
if (self.re.no_http.test(tail)) {
|
||
// should not be `://` & `///`, that protects from errors in protocol name
|
||
if (pos >= 3 && text[pos - 3] === ':') { return 0; }
|
||
if (pos >= 3 && text[pos - 3] === '/') { return 0; }
|
||
return tail.match(self.re.no_http)[0].length;
|
||
}
|
||
return 0;
|
||
}
|
||
},
|
||
'mailto:': {
|
||
validate: function (text, pos, self) {
|
||
var tail = text.slice(pos);
|
||
|
||
if (!self.re.mailto) {
|
||
self.re.mailto = new RegExp(
|
||
'^' + self.re.src_email_name + '@' + self.re.src_host_strict, 'i'
|
||
);
|
||
}
|
||
if (self.re.mailto.test(tail)) {
|
||
return tail.match(self.re.mailto)[0].length;
|
||
}
|
||
return 0;
|
||
}
|
||
}
|
||
};
|
||
|
||
/*eslint-disable max-len*/
|
||
|
||
// RE pattern for 2-character tlds (autogenerated by ./support/tlds_2char_gen.js)
|
||
var tlds_2ch_src_re = 'a[cdefgilmnoqrstuwxz]|b[abdefghijmnorstvwyz]|c[acdfghiklmnoruvwxyz]|d[ejkmoz]|e[cegrstu]|f[ijkmor]|g[abdefghilmnpqrstuwy]|h[kmnrtu]|i[delmnoqrst]|j[emop]|k[eghimnprwyz]|l[abcikrstuvy]|m[acdeghklmnopqrstuvwxyz]|n[acefgilopruz]|om|p[aefghklmnrstwy]|qa|r[eosuw]|s[abcdeghijklmnortuvxyz]|t[cdfghjklmnortvwz]|u[agksyz]|v[aceginu]|w[fs]|y[et]|z[amw]';
|
||
|
||
// DON'T try to make PRs with changes. Extend TLDs with LinkifyIt.tlds() instead
|
||
var tlds_default = 'biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|рф'.split('|');
|
||
|
||
/*eslint-enable max-len*/
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
|
||
function resetScanCache(self) {
|
||
self.__index__ = -1;
|
||
self.__text_cache__ = '';
|
||
}
|
||
|
||
function createValidator(re) {
|
||
return function (text, pos) {
|
||
var tail = text.slice(pos);
|
||
|
||
if (re.test(tail)) {
|
||
return tail.match(re)[0].length;
|
||
}
|
||
return 0;
|
||
};
|
||
}
|
||
|
||
function createNormalizer() {
|
||
return function (match, self) {
|
||
self.normalize(match);
|
||
};
|
||
}
|
||
|
||
// Schemas compiler. Build regexps.
|
||
//
|
||
function compile(self) {
|
||
|
||
// Load & clone RE patterns.
|
||
var re$1 = self.re = re(self.__opts__);
|
||
|
||
// Define dynamic patterns
|
||
var tlds = self.__tlds__.slice();
|
||
|
||
self.onCompile();
|
||
|
||
if (!self.__tlds_replaced__) {
|
||
tlds.push(tlds_2ch_src_re);
|
||
}
|
||
tlds.push(re$1.src_xn);
|
||
|
||
re$1.src_tlds = tlds.join('|');
|
||
|
||
function untpl(tpl) { return tpl.replace('%TLDS%', re$1.src_tlds); }
|
||
|
||
re$1.email_fuzzy = RegExp(untpl(re$1.tpl_email_fuzzy), 'i');
|
||
re$1.link_fuzzy = RegExp(untpl(re$1.tpl_link_fuzzy), 'i');
|
||
re$1.link_no_ip_fuzzy = RegExp(untpl(re$1.tpl_link_no_ip_fuzzy), 'i');
|
||
re$1.host_fuzzy_test = RegExp(untpl(re$1.tpl_host_fuzzy_test), 'i');
|
||
|
||
//
|
||
// Compile each schema
|
||
//
|
||
|
||
var aliases = [];
|
||
|
||
self.__compiled__ = {}; // Reset compiled data
|
||
|
||
function schemaError(name, val) {
|
||
throw new Error('(LinkifyIt) Invalid schema "' + name + '": ' + val);
|
||
}
|
||
|
||
Object.keys(self.__schemas__).forEach(function (name) {
|
||
var val = self.__schemas__[name];
|
||
|
||
// skip disabled methods
|
||
if (val === null) { return; }
|
||
|
||
var compiled = { validate: null, link: null };
|
||
|
||
self.__compiled__[name] = compiled;
|
||
|
||
if (isObject(val)) {
|
||
if (isRegExp(val.validate)) {
|
||
compiled.validate = createValidator(val.validate);
|
||
} else if (isFunction(val.validate)) {
|
||
compiled.validate = val.validate;
|
||
} else {
|
||
schemaError(name, val);
|
||
}
|
||
|
||
if (isFunction(val.normalize)) {
|
||
compiled.normalize = val.normalize;
|
||
} else if (!val.normalize) {
|
||
compiled.normalize = createNormalizer();
|
||
} else {
|
||
schemaError(name, val);
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
if (isString(val)) {
|
||
aliases.push(name);
|
||
return;
|
||
}
|
||
|
||
schemaError(name, val);
|
||
});
|
||
|
||
//
|
||
// Compile postponed aliases
|
||
//
|
||
|
||
aliases.forEach(function (alias) {
|
||
if (!self.__compiled__[self.__schemas__[alias]]) {
|
||
// Silently fail on missed schemas to avoid errons on disable.
|
||
// schemaError(alias, self.__schemas__[alias]);
|
||
return;
|
||
}
|
||
|
||
self.__compiled__[alias].validate =
|
||
self.__compiled__[self.__schemas__[alias]].validate;
|
||
self.__compiled__[alias].normalize =
|
||
self.__compiled__[self.__schemas__[alias]].normalize;
|
||
});
|
||
|
||
//
|
||
// Fake record for guessed links
|
||
//
|
||
self.__compiled__[''] = { validate: null, normalize: createNormalizer() };
|
||
|
||
//
|
||
// Build schema condition
|
||
//
|
||
var slist = Object.keys(self.__compiled__)
|
||
.filter(function (name) {
|
||
// Filter disabled & fake schemas
|
||
return name.length > 0 && self.__compiled__[name];
|
||
})
|
||
.map(escapeRE)
|
||
.join('|');
|
||
// (?!_) cause 1.5x slowdown
|
||
self.re.schema_test = RegExp('(^|(?!_)(?:[><\uff5c]|' + re$1.src_ZPCc + '))(' + slist + ')', 'i');
|
||
self.re.schema_search = RegExp('(^|(?!_)(?:[><\uff5c]|' + re$1.src_ZPCc + '))(' + slist + ')', 'ig');
|
||
|
||
self.re.pretest = RegExp(
|
||
'(' + self.re.schema_test.source + ')|(' + self.re.host_fuzzy_test.source + ')|@',
|
||
'i'
|
||
);
|
||
|
||
//
|
||
// Cleanup
|
||
//
|
||
|
||
resetScanCache(self);
|
||
}
|
||
|
||
/**
|
||
* class Match
|
||
*
|
||
* Match result. Single element of array, returned by [[LinkifyIt#match]]
|
||
**/
|
||
function Match(self, shift) {
|
||
var start = self.__index__,
|
||
end = self.__last_index__,
|
||
text = self.__text_cache__.slice(start, end);
|
||
|
||
/**
|
||
* Match#schema -> String
|
||
*
|
||
* Prefix (protocol) for matched string.
|
||
**/
|
||
this.schema = self.__schema__.toLowerCase();
|
||
/**
|
||
* Match#index -> Number
|
||
*
|
||
* First position of matched string.
|
||
**/
|
||
this.index = start + shift;
|
||
/**
|
||
* Match#lastIndex -> Number
|
||
*
|
||
* Next position after matched string.
|
||
**/
|
||
this.lastIndex = end + shift;
|
||
/**
|
||
* Match#raw -> String
|
||
*
|
||
* Matched string.
|
||
**/
|
||
this.raw = text;
|
||
/**
|
||
* Match#text -> String
|
||
*
|
||
* Notmalized text of matched string.
|
||
**/
|
||
this.text = text;
|
||
/**
|
||
* Match#url -> String
|
||
*
|
||
* Normalized url of matched string.
|
||
**/
|
||
this.url = text;
|
||
}
|
||
|
||
function createMatch(self, shift) {
|
||
var match = new Match(self, shift);
|
||
|
||
self.__compiled__[match.schema].normalize(match, self);
|
||
|
||
return match;
|
||
}
|
||
|
||
|
||
/**
|
||
* class LinkifyIt
|
||
**/
|
||
|
||
/**
|
||
* new LinkifyIt(schemas, options)
|
||
* - schemas (Object): Optional. Additional schemas to validate (prefix/validator)
|
||
* - options (Object): { fuzzyLink|fuzzyEmail|fuzzyIP: true|false }
|
||
*
|
||
* Creates new linkifier instance with optional additional schemas.
|
||
* Can be called without `new` keyword for convenience.
|
||
*
|
||
* By default understands:
|
||
*
|
||
* - `http(s)://...` , `ftp://...`, `mailto:...` & `//...` links
|
||
* - "fuzzy" links and emails (example.com, foo@bar.com).
|
||
*
|
||
* `schemas` is an object, where each key/value describes protocol/rule:
|
||
*
|
||
* - __key__ - link prefix (usually, protocol name with `:` at the end, `skype:`
|
||
* for example). `linkify-it` makes shure that prefix is not preceeded with
|
||
* alphanumeric char and symbols. Only whitespaces and punctuation allowed.
|
||
* - __value__ - rule to check tail after link prefix
|
||
* - _String_ - just alias to existing rule
|
||
* - _Object_
|
||
* - _validate_ - validator function (should return matched length on success),
|
||
* or `RegExp`.
|
||
* - _normalize_ - optional function to normalize text & url of matched result
|
||
* (for example, for @twitter mentions).
|
||
*
|
||
* `options`:
|
||
*
|
||
* - __fuzzyLink__ - recognige URL-s without `http(s):` prefix. Default `true`.
|
||
* - __fuzzyIP__ - allow IPs in fuzzy links above. Can conflict with some texts
|
||
* like version numbers. Default `false`.
|
||
* - __fuzzyEmail__ - recognize emails without `mailto:` prefix.
|
||
*
|
||
**/
|
||
function LinkifyIt$1(schemas, options) {
|
||
if (!(this instanceof LinkifyIt$1)) {
|
||
return new LinkifyIt$1(schemas, options);
|
||
}
|
||
|
||
if (!options) {
|
||
if (isOptionsObj(schemas)) {
|
||
options = schemas;
|
||
schemas = {};
|
||
}
|
||
}
|
||
|
||
this.__opts__ = assign({}, defaultOptions, options);
|
||
|
||
// Cache last tested result. Used to skip repeating steps on next `match` call.
|
||
this.__index__ = -1;
|
||
this.__last_index__ = -1; // Next scan position
|
||
this.__schema__ = '';
|
||
this.__text_cache__ = '';
|
||
|
||
this.__schemas__ = assign({}, defaultSchemas, schemas);
|
||
this.__compiled__ = {};
|
||
|
||
this.__tlds__ = tlds_default;
|
||
this.__tlds_replaced__ = false;
|
||
|
||
this.re = {};
|
||
|
||
compile(this);
|
||
}
|
||
|
||
|
||
/** chainable
|
||
* LinkifyIt#add(schema, definition)
|
||
* - schema (String): rule name (fixed pattern prefix)
|
||
* - definition (String|RegExp|Object): schema definition
|
||
*
|
||
* Add new rule definition. See constructor description for details.
|
||
**/
|
||
LinkifyIt$1.prototype.add = function add(schema, definition) {
|
||
this.__schemas__[schema] = definition;
|
||
compile(this);
|
||
return this;
|
||
};
|
||
|
||
|
||
/** chainable
|
||
* LinkifyIt#set(options)
|
||
* - options (Object): { fuzzyLink|fuzzyEmail|fuzzyIP: true|false }
|
||
*
|
||
* Set recognition options for links without schema.
|
||
**/
|
||
LinkifyIt$1.prototype.set = function set(options) {
|
||
this.__opts__ = assign(this.__opts__, options);
|
||
return this;
|
||
};
|
||
|
||
|
||
/**
|
||
* LinkifyIt#test(text) -> Boolean
|
||
*
|
||
* Searches linkifiable pattern and returns `true` on success or `false` on fail.
|
||
**/
|
||
LinkifyIt$1.prototype.test = function test(text) {
|
||
// Reset scan cache
|
||
this.__text_cache__ = text;
|
||
this.__index__ = -1;
|
||
|
||
if (!text.length) { return false; }
|
||
|
||
var m, ml, me, len, shift, next, re, tld_pos, at_pos;
|
||
|
||
// try to scan for link with schema - that's the most simple rule
|
||
if (this.re.schema_test.test(text)) {
|
||
re = this.re.schema_search;
|
||
re.lastIndex = 0;
|
||
while ((m = re.exec(text)) !== null) {
|
||
len = this.testSchemaAt(text, m[2], re.lastIndex);
|
||
if (len) {
|
||
this.__schema__ = m[2];
|
||
this.__index__ = m.index + m[1].length;
|
||
this.__last_index__ = m.index + m[0].length + len;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (this.__opts__.fuzzyLink && this.__compiled__['http:']) {
|
||
// guess schemaless links
|
||
tld_pos = text.search(this.re.host_fuzzy_test);
|
||
if (tld_pos >= 0) {
|
||
// if tld is located after found link - no need to check fuzzy pattern
|
||
if (this.__index__ < 0 || tld_pos < this.__index__) {
|
||
if ((ml = text.match(this.__opts__.fuzzyIP ? this.re.link_fuzzy : this.re.link_no_ip_fuzzy)) !== null) {
|
||
|
||
shift = ml.index + ml[1].length;
|
||
|
||
if (this.__index__ < 0 || shift < this.__index__) {
|
||
this.__schema__ = '';
|
||
this.__index__ = shift;
|
||
this.__last_index__ = ml.index + ml[0].length;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (this.__opts__.fuzzyEmail && this.__compiled__['mailto:']) {
|
||
// guess schemaless emails
|
||
at_pos = text.indexOf('@');
|
||
if (at_pos >= 0) {
|
||
// We can't skip this check, because this cases are possible:
|
||
// 192.168.1.1@gmail.com, my.in@example.com
|
||
if ((me = text.match(this.re.email_fuzzy)) !== null) {
|
||
|
||
shift = me.index + me[1].length;
|
||
next = me.index + me[0].length;
|
||
|
||
if (this.__index__ < 0 || shift < this.__index__ ||
|
||
(shift === this.__index__ && next > this.__last_index__)) {
|
||
this.__schema__ = 'mailto:';
|
||
this.__index__ = shift;
|
||
this.__last_index__ = next;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return this.__index__ >= 0;
|
||
};
|
||
|
||
|
||
/**
|
||
* LinkifyIt#pretest(text) -> Boolean
|
||
*
|
||
* Very quick check, that can give false positives. Returns true if link MAY BE
|
||
* can exists. Can be used for speed optimization, when you need to check that
|
||
* link NOT exists.
|
||
**/
|
||
LinkifyIt$1.prototype.pretest = function pretest(text) {
|
||
return this.re.pretest.test(text);
|
||
};
|
||
|
||
|
||
/**
|
||
* LinkifyIt#testSchemaAt(text, name, position) -> Number
|
||
* - text (String): text to scan
|
||
* - name (String): rule (schema) name
|
||
* - position (Number): text offset to check from
|
||
*
|
||
* Similar to [[LinkifyIt#test]] but checks only specific protocol tail exactly
|
||
* at given position. Returns length of found pattern (0 on fail).
|
||
**/
|
||
LinkifyIt$1.prototype.testSchemaAt = function testSchemaAt(text, schema, pos) {
|
||
// If not supported schema check requested - terminate
|
||
if (!this.__compiled__[schema.toLowerCase()]) {
|
||
return 0;
|
||
}
|
||
return this.__compiled__[schema.toLowerCase()].validate(text, pos, this);
|
||
};
|
||
|
||
|
||
/**
|
||
* LinkifyIt#match(text) -> Array|null
|
||
*
|
||
* Returns array of found link descriptions or `null` on fail. We strongly
|
||
* recommend to use [[LinkifyIt#test]] first, for best speed.
|
||
*
|
||
* ##### Result match description
|
||
*
|
||
* - __schema__ - link schema, can be empty for fuzzy links, or `//` for
|
||
* protocol-neutral links.
|
||
* - __index__ - offset of matched text
|
||
* - __lastIndex__ - index of next char after mathch end
|
||
* - __raw__ - matched text
|
||
* - __text__ - normalized text
|
||
* - __url__ - link, generated from matched text
|
||
**/
|
||
LinkifyIt$1.prototype.match = function match(text) {
|
||
var shift = 0, result = [];
|
||
|
||
// Try to take previous element from cache, if .test() called before
|
||
if (this.__index__ >= 0 && this.__text_cache__ === text) {
|
||
result.push(createMatch(this, shift));
|
||
shift = this.__last_index__;
|
||
}
|
||
|
||
// Cut head if cache was used
|
||
var tail = shift ? text.slice(shift) : text;
|
||
|
||
// Scan string until end reached
|
||
while (this.test(tail)) {
|
||
result.push(createMatch(this, shift));
|
||
|
||
tail = tail.slice(this.__last_index__);
|
||
shift += this.__last_index__;
|
||
}
|
||
|
||
if (result.length) {
|
||
return result;
|
||
}
|
||
|
||
return null;
|
||
};
|
||
|
||
|
||
/** chainable
|
||
* LinkifyIt#tlds(list [, keepOld]) -> this
|
||
* - list (Array): list of tlds
|
||
* - keepOld (Boolean): merge with current list if `true` (`false` by default)
|
||
*
|
||
* Load (or merge) new tlds list. Those are user for fuzzy links (without prefix)
|
||
* to avoid false positives. By default this algorythm used:
|
||
*
|
||
* - hostname with any 2-letter root zones are ok.
|
||
* - biz|com|edu|gov|net|org|pro|web|xxx|aero|asia|coop|info|museum|name|shop|рф
|
||
* are ok.
|
||
* - encoded (`xn--...`) root zones are ok.
|
||
*
|
||
* If list is replaced, then exact match for 2-chars root zones will be checked.
|
||
**/
|
||
LinkifyIt$1.prototype.tlds = function tlds(list, keepOld) {
|
||
list = Array.isArray(list) ? list : [ list ];
|
||
|
||
if (!keepOld) {
|
||
this.__tlds__ = list.slice();
|
||
this.__tlds_replaced__ = true;
|
||
compile(this);
|
||
return this;
|
||
}
|
||
|
||
this.__tlds__ = this.__tlds__.concat(list)
|
||
.sort()
|
||
.filter(function (el, idx, arr) {
|
||
return el !== arr[idx - 1];
|
||
})
|
||
.reverse();
|
||
|
||
compile(this);
|
||
return this;
|
||
};
|
||
|
||
/**
|
||
* LinkifyIt#normalize(match)
|
||
*
|
||
* Default normalizer (if schema does not define it's own).
|
||
**/
|
||
LinkifyIt$1.prototype.normalize = function normalize(match) {
|
||
|
||
// Do minimal possible changes by default. Need to collect feedback prior
|
||
// to move forward https://github.com/markdown-it/linkify-it/issues/1
|
||
|
||
if (!match.schema) { match.url = 'http://' + match.url; }
|
||
|
||
if (match.schema === 'mailto:' && !/^mailto:/i.test(match.url)) {
|
||
match.url = 'mailto:' + match.url;
|
||
}
|
||
};
|
||
|
||
|
||
/**
|
||
* LinkifyIt#onCompile()
|
||
*
|
||
* Override to modify basic RegExp-s.
|
||
**/
|
||
LinkifyIt$1.prototype.onCompile = function onCompile() {
|
||
};
|
||
|
||
|
||
var linkifyIt = LinkifyIt$1;
|
||
|
||
/** Highest positive signed 32-bit float value */
|
||
const maxInt = 2147483647; // aka. 0x7FFFFFFF or 2^31-1
|
||
|
||
/** Bootstring parameters */
|
||
const base = 36;
|
||
const tMin = 1;
|
||
const tMax = 26;
|
||
const skew = 38;
|
||
const damp = 700;
|
||
const initialBias = 72;
|
||
const initialN = 128; // 0x80
|
||
const delimiter = '-'; // '\x2D'
|
||
|
||
/** Regular expressions */
|
||
const regexPunycode = /^xn--/;
|
||
const regexNonASCII = /[^\0-\x7E]/; // non-ASCII chars
|
||
const regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g; // RFC 3490 separators
|
||
|
||
/** Error messages */
|
||
const errors = {
|
||
'overflow': 'Overflow: input needs wider integers to process',
|
||
'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
|
||
'invalid-input': 'Invalid input'
|
||
};
|
||
|
||
/** Convenience shortcuts */
|
||
const baseMinusTMin = base - tMin;
|
||
const floor = Math.floor;
|
||
const stringFromCharCode = String.fromCharCode;
|
||
|
||
/*--------------------------------------------------------------------------*/
|
||
|
||
/**
|
||
* A generic error utility function.
|
||
* @private
|
||
* @param {String} type The error type.
|
||
* @returns {Error} Throws a `RangeError` with the applicable error message.
|
||
*/
|
||
function error(type) {
|
||
throw new RangeError(errors[type]);
|
||
}
|
||
|
||
/**
|
||
* A generic `Array#map` utility function.
|
||
* @private
|
||
* @param {Array} array The array to iterate over.
|
||
* @param {Function} callback The function that gets called for every array
|
||
* item.
|
||
* @returns {Array} A new array of values returned by the callback function.
|
||
*/
|
||
function map(array, fn) {
|
||
const result = [];
|
||
let length = array.length;
|
||
while (length--) {
|
||
result[length] = fn(array[length]);
|
||
}
|
||
return result;
|
||
}
|
||
|
||
/**
|
||
* A simple `Array#map`-like wrapper to work with domain name strings or email
|
||
* addresses.
|
||
* @private
|
||
* @param {String} domain The domain name or email address.
|
||
* @param {Function} callback The function that gets called for every
|
||
* character.
|
||
* @returns {Array} A new string of characters returned by the callback
|
||
* function.
|
||
*/
|
||
function mapDomain(string, fn) {
|
||
const parts = string.split('@');
|
||
let result = '';
|
||
if (parts.length > 1) {
|
||
// In email addresses, only the domain name should be punycoded. Leave
|
||
// the local part (i.e. everything up to `@`) intact.
|
||
result = parts[0] + '@';
|
||
string = parts[1];
|
||
}
|
||
// Avoid `split(regex)` for IE8 compatibility. See #17.
|
||
string = string.replace(regexSeparators, '\x2E');
|
||
const labels = string.split('.');
|
||
const encoded = map(labels, fn).join('.');
|
||
return result + encoded;
|
||
}
|
||
|
||
/**
|
||
* Creates an array containing the numeric code points of each Unicode
|
||
* character in the string. While JavaScript uses UCS-2 internally,
|
||
* this function will convert a pair of surrogate halves (each of which
|
||
* UCS-2 exposes as separate characters) into a single code point,
|
||
* matching UTF-16.
|
||
* @see `punycode.ucs2.encode`
|
||
* @see <https://mathiasbynens.be/notes/javascript-encoding>
|
||
* @memberOf punycode.ucs2
|
||
* @name decode
|
||
* @param {String} string The Unicode input string (UCS-2).
|
||
* @returns {Array} The new array of code points.
|
||
*/
|
||
function ucs2decode(string) {
|
||
const output = [];
|
||
let counter = 0;
|
||
const length = string.length;
|
||
while (counter < length) {
|
||
const value = string.charCodeAt(counter++);
|
||
if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
|
||
// It's a high surrogate, and there is a next character.
|
||
const extra = string.charCodeAt(counter++);
|
||
if ((extra & 0xFC00) == 0xDC00) { // Low surrogate.
|
||
output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
|
||
} else {
|
||
// It's an unmatched surrogate; only append this code unit, in case the
|
||
// next code unit is the high surrogate of a surrogate pair.
|
||
output.push(value);
|
||
counter--;
|
||
}
|
||
} else {
|
||
output.push(value);
|
||
}
|
||
}
|
||
return output;
|
||
}
|
||
|
||
/**
|
||
* Creates a string based on an array of numeric code points.
|
||
* @see `punycode.ucs2.decode`
|
||
* @memberOf punycode.ucs2
|
||
* @name encode
|
||
* @param {Array} codePoints The array of numeric code points.
|
||
* @returns {String} The new Unicode string (UCS-2).
|
||
*/
|
||
const ucs2encode = array => String.fromCodePoint(...array);
|
||
|
||
/**
|
||
* Converts a basic code point into a digit/integer.
|
||
* @see `digitToBasic()`
|
||
* @private
|
||
* @param {Number} codePoint The basic numeric code point value.
|
||
* @returns {Number} The numeric value of a basic code point (for use in
|
||
* representing integers) in the range `0` to `base - 1`, or `base` if
|
||
* the code point does not represent a value.
|
||
*/
|
||
const basicToDigit = function(codePoint) {
|
||
if (codePoint - 0x30 < 0x0A) {
|
||
return codePoint - 0x16;
|
||
}
|
||
if (codePoint - 0x41 < 0x1A) {
|
||
return codePoint - 0x41;
|
||
}
|
||
if (codePoint - 0x61 < 0x1A) {
|
||
return codePoint - 0x61;
|
||
}
|
||
return base;
|
||
};
|
||
|
||
/**
|
||
* Converts a digit/integer into a basic code point.
|
||
* @see `basicToDigit()`
|
||
* @private
|
||
* @param {Number} digit The numeric value of a basic code point.
|
||
* @returns {Number} The basic code point whose value (when used for
|
||
* representing integers) is `digit`, which needs to be in the range
|
||
* `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
|
||
* used; else, the lowercase form is used. The behavior is undefined
|
||
* if `flag` is non-zero and `digit` has no uppercase form.
|
||
*/
|
||
const digitToBasic = function(digit, flag) {
|
||
// 0..25 map to ASCII a..z or A..Z
|
||
// 26..35 map to ASCII 0..9
|
||
return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
|
||
};
|
||
|
||
/**
|
||
* Bias adaptation function as per section 3.4 of RFC 3492.
|
||
* https://tools.ietf.org/html/rfc3492#section-3.4
|
||
* @private
|
||
*/
|
||
const adapt = function(delta, numPoints, firstTime) {
|
||
let k = 0;
|
||
delta = firstTime ? floor(delta / damp) : delta >> 1;
|
||
delta += floor(delta / numPoints);
|
||
for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
|
||
delta = floor(delta / baseMinusTMin);
|
||
}
|
||
return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
|
||
};
|
||
|
||
/**
|
||
* Converts a Punycode string of ASCII-only symbols to a string of Unicode
|
||
* symbols.
|
||
* @memberOf punycode
|
||
* @param {String} input The Punycode string of ASCII-only symbols.
|
||
* @returns {String} The resulting string of Unicode symbols.
|
||
*/
|
||
const decode = function(input) {
|
||
// Don't use UCS-2.
|
||
const output = [];
|
||
const inputLength = input.length;
|
||
let i = 0;
|
||
let n = initialN;
|
||
let bias = initialBias;
|
||
|
||
// Handle the basic code points: let `basic` be the number of input code
|
||
// points before the last delimiter, or `0` if there is none, then copy
|
||
// the first basic code points to the output.
|
||
|
||
let basic = input.lastIndexOf(delimiter);
|
||
if (basic < 0) {
|
||
basic = 0;
|
||
}
|
||
|
||
for (let j = 0; j < basic; ++j) {
|
||
// if it's not a basic code point
|
||
if (input.charCodeAt(j) >= 0x80) {
|
||
error('not-basic');
|
||
}
|
||
output.push(input.charCodeAt(j));
|
||
}
|
||
|
||
// Main decoding loop: start just after the last delimiter if any basic code
|
||
// points were copied; start at the beginning otherwise.
|
||
|
||
for (let index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
|
||
|
||
// `index` is the index of the next character to be consumed.
|
||
// Decode a generalized variable-length integer into `delta`,
|
||
// which gets added to `i`. The overflow checking is easier
|
||
// if we increase `i` as we go, then subtract off its starting
|
||
// value at the end to obtain `delta`.
|
||
let oldi = i;
|
||
for (let w = 1, k = base; /* no condition */; k += base) {
|
||
|
||
if (index >= inputLength) {
|
||
error('invalid-input');
|
||
}
|
||
|
||
const digit = basicToDigit(input.charCodeAt(index++));
|
||
|
||
if (digit >= base || digit > floor((maxInt - i) / w)) {
|
||
error('overflow');
|
||
}
|
||
|
||
i += digit * w;
|
||
const t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
|
||
|
||
if (digit < t) {
|
||
break;
|
||
}
|
||
|
||
const baseMinusT = base - t;
|
||
if (w > floor(maxInt / baseMinusT)) {
|
||
error('overflow');
|
||
}
|
||
|
||
w *= baseMinusT;
|
||
|
||
}
|
||
|
||
const out = output.length + 1;
|
||
bias = adapt(i - oldi, out, oldi == 0);
|
||
|
||
// `i` was supposed to wrap around from `out` to `0`,
|
||
// incrementing `n` each time, so we'll fix that now:
|
||
if (floor(i / out) > maxInt - n) {
|
||
error('overflow');
|
||
}
|
||
|
||
n += floor(i / out);
|
||
i %= out;
|
||
|
||
// Insert `n` at position `i` of the output.
|
||
output.splice(i++, 0, n);
|
||
|
||
}
|
||
|
||
return String.fromCodePoint(...output);
|
||
};
|
||
|
||
/**
|
||
* Converts a string of Unicode symbols (e.g. a domain name label) to a
|
||
* Punycode string of ASCII-only symbols.
|
||
* @memberOf punycode
|
||
* @param {String} input The string of Unicode symbols.
|
||
* @returns {String} The resulting Punycode string of ASCII-only symbols.
|
||
*/
|
||
const encode = function(input) {
|
||
const output = [];
|
||
|
||
// Convert the input in UCS-2 to an array of Unicode code points.
|
||
input = ucs2decode(input);
|
||
|
||
// Cache the length.
|
||
let inputLength = input.length;
|
||
|
||
// Initialize the state.
|
||
let n = initialN;
|
||
let delta = 0;
|
||
let bias = initialBias;
|
||
|
||
// Handle the basic code points.
|
||
for (const currentValue of input) {
|
||
if (currentValue < 0x80) {
|
||
output.push(stringFromCharCode(currentValue));
|
||
}
|
||
}
|
||
|
||
let basicLength = output.length;
|
||
let handledCPCount = basicLength;
|
||
|
||
// `handledCPCount` is the number of code points that have been handled;
|
||
// `basicLength` is the number of basic code points.
|
||
|
||
// Finish the basic string with a delimiter unless it's empty.
|
||
if (basicLength) {
|
||
output.push(delimiter);
|
||
}
|
||
|
||
// Main encoding loop:
|
||
while (handledCPCount < inputLength) {
|
||
|
||
// All non-basic code points < n have been handled already. Find the next
|
||
// larger one:
|
||
let m = maxInt;
|
||
for (const currentValue of input) {
|
||
if (currentValue >= n && currentValue < m) {
|
||
m = currentValue;
|
||
}
|
||
}
|
||
|
||
// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
|
||
// but guard against overflow.
|
||
const handledCPCountPlusOne = handledCPCount + 1;
|
||
if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
|
||
error('overflow');
|
||
}
|
||
|
||
delta += (m - n) * handledCPCountPlusOne;
|
||
n = m;
|
||
|
||
for (const currentValue of input) {
|
||
if (currentValue < n && ++delta > maxInt) {
|
||
error('overflow');
|
||
}
|
||
if (currentValue == n) {
|
||
// Represent delta as a generalized variable-length integer.
|
||
let q = delta;
|
||
for (let k = base; /* no condition */; k += base) {
|
||
const t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
|
||
if (q < t) {
|
||
break;
|
||
}
|
||
const qMinusT = q - t;
|
||
const baseMinusT = base - t;
|
||
output.push(
|
||
stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
|
||
);
|
||
q = floor(qMinusT / baseMinusT);
|
||
}
|
||
|
||
output.push(stringFromCharCode(digitToBasic(q, 0)));
|
||
bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
|
||
delta = 0;
|
||
++handledCPCount;
|
||
}
|
||
}
|
||
|
||
++delta;
|
||
++n;
|
||
|
||
}
|
||
return output.join('');
|
||
};
|
||
|
||
/**
|
||
* Converts a Punycode string representing a domain name or an email address
|
||
* to Unicode. Only the Punycoded parts of the input will be converted, i.e.
|
||
* it doesn't matter if you call it on a string that has already been
|
||
* converted to Unicode.
|
||
* @memberOf punycode
|
||
* @param {String} input The Punycoded domain name or email address to
|
||
* convert to Unicode.
|
||
* @returns {String} The Unicode representation of the given Punycode
|
||
* string.
|
||
*/
|
||
const toUnicode = function(input) {
|
||
return mapDomain(input, function(string) {
|
||
return regexPunycode.test(string)
|
||
? decode(string.slice(4).toLowerCase())
|
||
: string;
|
||
});
|
||
};
|
||
|
||
/**
|
||
* Converts a Unicode string representing a domain name or an email address to
|
||
* Punycode. Only the non-ASCII parts of the domain name will be converted,
|
||
* i.e. it doesn't matter if you call it with a domain that's already in
|
||
* ASCII.
|
||
* @memberOf punycode
|
||
* @param {String} input The domain name or email address to convert, as a
|
||
* Unicode string.
|
||
* @returns {String} The Punycode representation of the given domain name or
|
||
* email address.
|
||
*/
|
||
const toASCII = function(input) {
|
||
return mapDomain(input, function(string) {
|
||
return regexNonASCII.test(string)
|
||
? 'xn--' + encode(string)
|
||
: string;
|
||
});
|
||
};
|
||
|
||
/*--------------------------------------------------------------------------*/
|
||
|
||
/** Define the public API */
|
||
const punycode$1 = {
|
||
/**
|
||
* A string representing the current Punycode.js version number.
|
||
* @memberOf punycode
|
||
* @type String
|
||
*/
|
||
'version': '2.1.0',
|
||
/**
|
||
* An object of methods to convert from JavaScript's internal character
|
||
* representation (UCS-2) to Unicode code points, and back.
|
||
* @see <https://mathiasbynens.be/notes/javascript-encoding>
|
||
* @memberOf punycode
|
||
* @type Object
|
||
*/
|
||
'ucs2': {
|
||
'decode': ucs2decode,
|
||
'encode': ucs2encode
|
||
},
|
||
'decode': decode,
|
||
'encode': encode,
|
||
'toASCII': toASCII,
|
||
'toUnicode': toUnicode
|
||
};
|
||
|
||
var punycode_1 = punycode$1;
|
||
|
||
var _default = {
|
||
options: {
|
||
html: false, // Enable HTML tags in source
|
||
xhtmlOut: false, // Use '/' to close single tags (<br />)
|
||
breaks: false, // Convert '\n' in paragraphs into <br>
|
||
langPrefix: 'language-', // CSS language prefix for fenced blocks
|
||
linkify: false, // autoconvert URL-like texts to links
|
||
|
||
// Enable some language-neutral replacements + quotes beautification
|
||
typographer: false,
|
||
|
||
// Double + single quotes replacement pairs, when typographer enabled,
|
||
// and smartquotes on. Could be either a String or an Array.
|
||
//
|
||
// For example, you can use '«»„“' for Russian, '„“‚‘' for German,
|
||
// and ['«\xA0', '\xA0»', '‹\xA0', '\xA0›'] for French (including nbsp).
|
||
quotes: '\u201c\u201d\u2018\u2019', /* “”‘’ */
|
||
|
||
// Highlighter function. Should return escaped HTML,
|
||
// or '' if the source string is not changed and should be escaped externaly.
|
||
// If result starts with <pre... internal wrapper is skipped.
|
||
//
|
||
// function (/*str, lang*/) { return ''; }
|
||
//
|
||
highlight: null,
|
||
|
||
maxNesting: 100 // Internal protection, recursion limit
|
||
},
|
||
|
||
components: {
|
||
|
||
core: {},
|
||
block: {},
|
||
inline: {}
|
||
}
|
||
};
|
||
|
||
var zero = {
|
||
options: {
|
||
html: false, // Enable HTML tags in source
|
||
xhtmlOut: false, // Use '/' to close single tags (<br />)
|
||
breaks: false, // Convert '\n' in paragraphs into <br>
|
||
langPrefix: 'language-', // CSS language prefix for fenced blocks
|
||
linkify: false, // autoconvert URL-like texts to links
|
||
|
||
// Enable some language-neutral replacements + quotes beautification
|
||
typographer: false,
|
||
|
||
// Double + single quotes replacement pairs, when typographer enabled,
|
||
// and smartquotes on. Could be either a String or an Array.
|
||
//
|
||
// For example, you can use '«»„“' for Russian, '„“‚‘' for German,
|
||
// and ['«\xA0', '\xA0»', '‹\xA0', '\xA0›'] for French (including nbsp).
|
||
quotes: '\u201c\u201d\u2018\u2019', /* “”‘’ */
|
||
|
||
// Highlighter function. Should return escaped HTML,
|
||
// or '' if the source string is not changed and should be escaped externaly.
|
||
// If result starts with <pre... internal wrapper is skipped.
|
||
//
|
||
// function (/*str, lang*/) { return ''; }
|
||
//
|
||
highlight: null,
|
||
|
||
maxNesting: 20 // Internal protection, recursion limit
|
||
},
|
||
|
||
components: {
|
||
|
||
core: {
|
||
rules: [
|
||
'normalize',
|
||
'block',
|
||
'inline'
|
||
]
|
||
},
|
||
|
||
block: {
|
||
rules: [
|
||
'paragraph'
|
||
]
|
||
},
|
||
|
||
inline: {
|
||
rules: [
|
||
'text'
|
||
],
|
||
rules2: [
|
||
'balance_pairs',
|
||
'text_collapse'
|
||
]
|
||
}
|
||
}
|
||
};
|
||
|
||
var commonmark = {
|
||
options: {
|
||
html: true, // Enable HTML tags in source
|
||
xhtmlOut: true, // Use '/' to close single tags (<br />)
|
||
breaks: false, // Convert '\n' in paragraphs into <br>
|
||
langPrefix: 'language-', // CSS language prefix for fenced blocks
|
||
linkify: false, // autoconvert URL-like texts to links
|
||
|
||
// Enable some language-neutral replacements + quotes beautification
|
||
typographer: false,
|
||
|
||
// Double + single quotes replacement pairs, when typographer enabled,
|
||
// and smartquotes on. Could be either a String or an Array.
|
||
//
|
||
// For example, you can use '«»„“' for Russian, '„“‚‘' for German,
|
||
// and ['«\xA0', '\xA0»', '‹\xA0', '\xA0›'] for French (including nbsp).
|
||
quotes: '\u201c\u201d\u2018\u2019', /* “”‘’ */
|
||
|
||
// Highlighter function. Should return escaped HTML,
|
||
// or '' if the source string is not changed and should be escaped externaly.
|
||
// If result starts with <pre... internal wrapper is skipped.
|
||
//
|
||
// function (/*str, lang*/) { return ''; }
|
||
//
|
||
highlight: null,
|
||
|
||
maxNesting: 20 // Internal protection, recursion limit
|
||
},
|
||
|
||
components: {
|
||
|
||
core: {
|
||
rules: [
|
||
'normalize',
|
||
'block',
|
||
'inline'
|
||
]
|
||
},
|
||
|
||
block: {
|
||
rules: [
|
||
'blockquote',
|
||
'code',
|
||
'fence',
|
||
'heading',
|
||
'hr',
|
||
'html_block',
|
||
'lheading',
|
||
'list',
|
||
'reference',
|
||
'paragraph'
|
||
]
|
||
},
|
||
|
||
inline: {
|
||
rules: [
|
||
'autolink',
|
||
'backticks',
|
||
'emphasis',
|
||
'entity',
|
||
'escape',
|
||
'html_inline',
|
||
'image',
|
||
'link',
|
||
'newline',
|
||
'text'
|
||
],
|
||
rules2: [
|
||
'balance_pairs',
|
||
'emphasis',
|
||
'text_collapse'
|
||
]
|
||
}
|
||
}
|
||
};
|
||
|
||
var utils = utils$1;
|
||
var helpers = helpers$1;
|
||
var Renderer = renderer;
|
||
var ParserCore = parser_core;
|
||
var ParserBlock = parser_block;
|
||
var ParserInline = parser_inline;
|
||
var LinkifyIt = linkifyIt;
|
||
var mdurl = mdurl$1;
|
||
var punycode = punycode_1;
|
||
|
||
|
||
var config = {
|
||
default: _default,
|
||
zero: zero,
|
||
commonmark: commonmark
|
||
};
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
//
|
||
// This validator can prohibit more than really needed to prevent XSS. It's a
|
||
// tradeoff to keep code simple and to be secure by default.
|
||
//
|
||
// If you need different setup - override validator method as you wish. Or
|
||
// replace it with dummy function and use external sanitizer.
|
||
//
|
||
|
||
var BAD_PROTO_RE = /^(vbscript|javascript|file|data):/;
|
||
var GOOD_DATA_RE = /^data:image\/(gif|png|jpeg|webp);/;
|
||
|
||
function validateLink(url) {
|
||
// url should be normalized at this point, and existing entities are decoded
|
||
var str = url.trim().toLowerCase();
|
||
|
||
return BAD_PROTO_RE.test(str) ? (GOOD_DATA_RE.test(str) ? true : false) : true;
|
||
}
|
||
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
|
||
|
||
var RECODE_HOSTNAME_FOR = [ 'http:', 'https:', 'mailto:' ];
|
||
|
||
function normalizeLink(url) {
|
||
var parsed = mdurl.parse(url, true);
|
||
|
||
if (parsed.hostname) {
|
||
// Encode hostnames in urls like:
|
||
// `http://host/`, `https://host/`, `mailto:user@host`, `//host/`
|
||
//
|
||
// We don't encode unknown schemas, because it's likely that we encode
|
||
// something we shouldn't (e.g. `skype:name` treated as `skype:host`)
|
||
//
|
||
if (!parsed.protocol || RECODE_HOSTNAME_FOR.indexOf(parsed.protocol) >= 0) {
|
||
try {
|
||
parsed.hostname = punycode.toASCII(parsed.hostname);
|
||
} catch (er) { /**/ }
|
||
}
|
||
}
|
||
|
||
return mdurl.encode(mdurl.format(parsed));
|
||
}
|
||
|
||
function normalizeLinkText(url) {
|
||
var parsed = mdurl.parse(url, true);
|
||
|
||
if (parsed.hostname) {
|
||
// Encode hostnames in urls like:
|
||
// `http://host/`, `https://host/`, `mailto:user@host`, `//host/`
|
||
//
|
||
// We don't encode unknown schemas, because it's likely that we encode
|
||
// something we shouldn't (e.g. `skype:name` treated as `skype:host`)
|
||
//
|
||
if (!parsed.protocol || RECODE_HOSTNAME_FOR.indexOf(parsed.protocol) >= 0) {
|
||
try {
|
||
parsed.hostname = punycode.toUnicode(parsed.hostname);
|
||
} catch (er) { /**/ }
|
||
}
|
||
}
|
||
|
||
// add '%' to exclude list because of https://github.com/markdown-it/markdown-it/issues/720
|
||
return mdurl.decode(mdurl.format(parsed), mdurl.decode.defaultChars + '%');
|
||
}
|
||
|
||
|
||
/**
|
||
* class MarkdownIt
|
||
*
|
||
* Main parser/renderer class.
|
||
*
|
||
* ##### Usage
|
||
*
|
||
* ```javascript
|
||
* // node.js, "classic" way:
|
||
* var MarkdownIt = require('markdown-it'),
|
||
* md = new MarkdownIt();
|
||
* var result = md.render('# markdown-it rulezz!');
|
||
*
|
||
* // node.js, the same, but with sugar:
|
||
* var md = require('markdown-it')();
|
||
* var result = md.render('# markdown-it rulezz!');
|
||
*
|
||
* // browser without AMD, added to "window" on script load
|
||
* // Note, there are no dash.
|
||
* var md = window.markdownit();
|
||
* var result = md.render('# markdown-it rulezz!');
|
||
* ```
|
||
*
|
||
* Single line rendering, without paragraph wrap:
|
||
*
|
||
* ```javascript
|
||
* var md = require('markdown-it')();
|
||
* var result = md.renderInline('__markdown-it__ rulezz!');
|
||
* ```
|
||
**/
|
||
|
||
/**
|
||
* new MarkdownIt([presetName, options])
|
||
* - presetName (String): optional, `commonmark` / `zero`
|
||
* - options (Object)
|
||
*
|
||
* Creates parser instanse with given config. Can be called without `new`.
|
||
*
|
||
* ##### presetName
|
||
*
|
||
* MarkdownIt provides named presets as a convenience to quickly
|
||
* enable/disable active syntax rules and options for common use cases.
|
||
*
|
||
* - ["commonmark"](https://github.com/markdown-it/markdown-it/blob/master/lib/presets/commonmark.js) -
|
||
* configures parser to strict [CommonMark](http://commonmark.org/) mode.
|
||
* - [default](https://github.com/markdown-it/markdown-it/blob/master/lib/presets/default.js) -
|
||
* similar to GFM, used when no preset name given. Enables all available rules,
|
||
* but still without html, typographer & autolinker.
|
||
* - ["zero"](https://github.com/markdown-it/markdown-it/blob/master/lib/presets/zero.js) -
|
||
* all rules disabled. Useful to quickly setup your config via `.enable()`.
|
||
* For example, when you need only `bold` and `italic` markup and nothing else.
|
||
*
|
||
* ##### options:
|
||
*
|
||
* - __html__ - `false`. Set `true` to enable HTML tags in source. Be careful!
|
||
* That's not safe! You may need external sanitizer to protect output from XSS.
|
||
* It's better to extend features via plugins, instead of enabling HTML.
|
||
* - __xhtmlOut__ - `false`. Set `true` to add '/' when closing single tags
|
||
* (`<br />`). This is needed only for full CommonMark compatibility. In real
|
||
* world you will need HTML output.
|
||
* - __breaks__ - `false`. Set `true` to convert `\n` in paragraphs into `<br>`.
|
||
* - __langPrefix__ - `language-`. CSS language class prefix for fenced blocks.
|
||
* Can be useful for external highlighters.
|
||
* - __linkify__ - `false`. Set `true` to autoconvert URL-like text to links.
|
||
* - __typographer__ - `false`. Set `true` to enable [some language-neutral
|
||
* replacement](https://github.com/markdown-it/markdown-it/blob/master/lib/rules_core/replacements.js) +
|
||
* quotes beautification (smartquotes).
|
||
* - __quotes__ - `“”‘’`, String or Array. Double + single quotes replacement
|
||
* pairs, when typographer enabled and smartquotes on. For example, you can
|
||
* use `'«»„“'` for Russian, `'„“‚‘'` for German, and
|
||
* `['«\xA0', '\xA0»', '‹\xA0', '\xA0›']` for French (including nbsp).
|
||
* - __highlight__ - `null`. Highlighter function for fenced code blocks.
|
||
* Highlighter `function (str, lang)` should return escaped HTML. It can also
|
||
* return empty string if the source was not changed and should be escaped
|
||
* externaly. If result starts with <pre... internal wrapper is skipped.
|
||
*
|
||
* ##### Example
|
||
*
|
||
* ```javascript
|
||
* // commonmark mode
|
||
* var md = require('markdown-it')('commonmark');
|
||
*
|
||
* // default mode
|
||
* var md = require('markdown-it')();
|
||
*
|
||
* // enable everything
|
||
* var md = require('markdown-it')({
|
||
* html: true,
|
||
* linkify: true,
|
||
* typographer: true
|
||
* });
|
||
* ```
|
||
*
|
||
* ##### Syntax highlighting
|
||
*
|
||
* ```js
|
||
* var hljs = require('highlight.js') // https://highlightjs.org/
|
||
*
|
||
* var md = require('markdown-it')({
|
||
* highlight: function (str, lang) {
|
||
* if (lang && hljs.getLanguage(lang)) {
|
||
* try {
|
||
* return hljs.highlight(str, { language: lang, ignoreIllegals: true }).value;
|
||
* } catch (__) {}
|
||
* }
|
||
*
|
||
* return ''; // use external default escaping
|
||
* }
|
||
* });
|
||
* ```
|
||
*
|
||
* Or with full wrapper override (if you need assign class to `<pre>`):
|
||
*
|
||
* ```javascript
|
||
* var hljs = require('highlight.js') // https://highlightjs.org/
|
||
*
|
||
* // Actual default values
|
||
* var md = require('markdown-it')({
|
||
* highlight: function (str, lang) {
|
||
* if (lang && hljs.getLanguage(lang)) {
|
||
* try {
|
||
* return '<pre class="hljs"><code>' +
|
||
* hljs.highlight(str, { language: lang, ignoreIllegals: true }).value +
|
||
* '</code></pre>';
|
||
* } catch (__) {}
|
||
* }
|
||
*
|
||
* return '<pre class="hljs"><code>' + md.utils.escapeHtml(str) + '</code></pre>';
|
||
* }
|
||
* });
|
||
* ```
|
||
*
|
||
**/
|
||
function MarkdownIt(presetName, options) {
|
||
if (!(this instanceof MarkdownIt)) {
|
||
return new MarkdownIt(presetName, options);
|
||
}
|
||
|
||
if (!options) {
|
||
if (!utils.isString(presetName)) {
|
||
options = presetName || {};
|
||
presetName = 'default';
|
||
}
|
||
}
|
||
|
||
/**
|
||
* MarkdownIt#inline -> ParserInline
|
||
*
|
||
* Instance of [[ParserInline]]. You may need it to add new rules when
|
||
* writing plugins. For simple rules control use [[MarkdownIt.disable]] and
|
||
* [[MarkdownIt.enable]].
|
||
**/
|
||
this.inline = new ParserInline();
|
||
|
||
/**
|
||
* MarkdownIt#block -> ParserBlock
|
||
*
|
||
* Instance of [[ParserBlock]]. You may need it to add new rules when
|
||
* writing plugins. For simple rules control use [[MarkdownIt.disable]] and
|
||
* [[MarkdownIt.enable]].
|
||
**/
|
||
this.block = new ParserBlock();
|
||
|
||
/**
|
||
* MarkdownIt#core -> Core
|
||
*
|
||
* Instance of [[Core]] chain executor. You may need it to add new rules when
|
||
* writing plugins. For simple rules control use [[MarkdownIt.disable]] and
|
||
* [[MarkdownIt.enable]].
|
||
**/
|
||
this.core = new ParserCore();
|
||
|
||
/**
|
||
* MarkdownIt#renderer -> Renderer
|
||
*
|
||
* Instance of [[Renderer]]. Use it to modify output look. Or to add rendering
|
||
* rules for new token types, generated by plugins.
|
||
*
|
||
* ##### Example
|
||
*
|
||
* ```javascript
|
||
* var md = require('markdown-it')();
|
||
*
|
||
* function myToken(tokens, idx, options, env, self) {
|
||
* //...
|
||
* return result;
|
||
* };
|
||
*
|
||
* md.renderer.rules['my_token'] = myToken
|
||
* ```
|
||
*
|
||
* See [[Renderer]] docs and [source code](https://github.com/markdown-it/markdown-it/blob/master/lib/renderer.js).
|
||
**/
|
||
this.renderer = new Renderer();
|
||
|
||
/**
|
||
* MarkdownIt#linkify -> LinkifyIt
|
||
*
|
||
* [linkify-it](https://github.com/markdown-it/linkify-it) instance.
|
||
* Used by [linkify](https://github.com/markdown-it/markdown-it/blob/master/lib/rules_core/linkify.js)
|
||
* rule.
|
||
**/
|
||
this.linkify = new LinkifyIt();
|
||
|
||
/**
|
||
* MarkdownIt#validateLink(url) -> Boolean
|
||
*
|
||
* Link validation function. CommonMark allows too much in links. By default
|
||
* we disable `javascript:`, `vbscript:`, `file:` schemas, and almost all `data:...` schemas
|
||
* except some embedded image types.
|
||
*
|
||
* You can change this behaviour:
|
||
*
|
||
* ```javascript
|
||
* var md = require('markdown-it')();
|
||
* // enable everything
|
||
* md.validateLink = function () { return true; }
|
||
* ```
|
||
**/
|
||
this.validateLink = validateLink;
|
||
|
||
/**
|
||
* MarkdownIt#normalizeLink(url) -> String
|
||
*
|
||
* Function used to encode link url to a machine-readable format,
|
||
* which includes url-encoding, punycode, etc.
|
||
**/
|
||
this.normalizeLink = normalizeLink;
|
||
|
||
/**
|
||
* MarkdownIt#normalizeLinkText(url) -> String
|
||
*
|
||
* Function used to decode link url to a human-readable format`
|
||
**/
|
||
this.normalizeLinkText = normalizeLinkText;
|
||
|
||
|
||
// Expose utils & helpers for easy acces from plugins
|
||
|
||
/**
|
||
* MarkdownIt#utils -> utils
|
||
*
|
||
* Assorted utility functions, useful to write plugins. See details
|
||
* [here](https://github.com/markdown-it/markdown-it/blob/master/lib/common/utils.js).
|
||
**/
|
||
this.utils = utils;
|
||
|
||
/**
|
||
* MarkdownIt#helpers -> helpers
|
||
*
|
||
* Link components parser functions, useful to write plugins. See details
|
||
* [here](https://github.com/markdown-it/markdown-it/blob/master/lib/helpers).
|
||
**/
|
||
this.helpers = utils.assign({}, helpers);
|
||
|
||
|
||
this.options = {};
|
||
this.configure(presetName);
|
||
|
||
if (options) { this.set(options); }
|
||
}
|
||
|
||
|
||
/** chainable
|
||
* MarkdownIt.set(options)
|
||
*
|
||
* Set parser options (in the same format as in constructor). Probably, you
|
||
* will never need it, but you can change options after constructor call.
|
||
*
|
||
* ##### Example
|
||
*
|
||
* ```javascript
|
||
* var md = require('markdown-it')()
|
||
* .set({ html: true, breaks: true })
|
||
* .set({ typographer, true });
|
||
* ```
|
||
*
|
||
* __Note:__ To achieve the best possible performance, don't modify a
|
||
* `markdown-it` instance options on the fly. If you need multiple configurations
|
||
* it's best to create multiple instances and initialize each with separate
|
||
* config.
|
||
**/
|
||
MarkdownIt.prototype.set = function (options) {
|
||
utils.assign(this.options, options);
|
||
return this;
|
||
};
|
||
|
||
|
||
/** chainable, internal
|
||
* MarkdownIt.configure(presets)
|
||
*
|
||
* Batch load of all options and compenent settings. This is internal method,
|
||
* and you probably will not need it. But if you will - see available presets
|
||
* and data structure [here](https://github.com/markdown-it/markdown-it/tree/master/lib/presets)
|
||
*
|
||
* We strongly recommend to use presets instead of direct config loads. That
|
||
* will give better compatibility with next versions.
|
||
**/
|
||
MarkdownIt.prototype.configure = function (presets) {
|
||
var self = this, presetName;
|
||
|
||
if (utils.isString(presets)) {
|
||
presetName = presets;
|
||
presets = config[presetName];
|
||
if (!presets) { throw new Error('Wrong `markdown-it` preset "' + presetName + '", check name'); }
|
||
}
|
||
|
||
if (!presets) { throw new Error('Wrong `markdown-it` preset, can\'t be empty'); }
|
||
|
||
if (presets.options) { self.set(presets.options); }
|
||
|
||
if (presets.components) {
|
||
Object.keys(presets.components).forEach(function (name) {
|
||
if (presets.components[name].rules) {
|
||
self[name].ruler.enableOnly(presets.components[name].rules);
|
||
}
|
||
if (presets.components[name].rules2) {
|
||
self[name].ruler2.enableOnly(presets.components[name].rules2);
|
||
}
|
||
});
|
||
}
|
||
return this;
|
||
};
|
||
|
||
|
||
/** chainable
|
||
* MarkdownIt.enable(list, ignoreInvalid)
|
||
* - list (String|Array): rule name or list of rule names to enable
|
||
* - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.
|
||
*
|
||
* Enable list or rules. It will automatically find appropriate components,
|
||
* containing rules with given names. If rule not found, and `ignoreInvalid`
|
||
* not set - throws exception.
|
||
*
|
||
* ##### Example
|
||
*
|
||
* ```javascript
|
||
* var md = require('markdown-it')()
|
||
* .enable(['sub', 'sup'])
|
||
* .disable('smartquotes');
|
||
* ```
|
||
**/
|
||
MarkdownIt.prototype.enable = function (list, ignoreInvalid) {
|
||
var result = [];
|
||
|
||
if (!Array.isArray(list)) { list = [ list ]; }
|
||
|
||
[ 'core', 'block', 'inline' ].forEach(function (chain) {
|
||
result = result.concat(this[chain].ruler.enable(list, true));
|
||
}, this);
|
||
|
||
result = result.concat(this.inline.ruler2.enable(list, true));
|
||
|
||
var missed = list.filter(function (name) { return result.indexOf(name) < 0; });
|
||
|
||
if (missed.length && !ignoreInvalid) {
|
||
throw new Error('MarkdownIt. Failed to enable unknown rule(s): ' + missed);
|
||
}
|
||
|
||
return this;
|
||
};
|
||
|
||
|
||
/** chainable
|
||
* MarkdownIt.disable(list, ignoreInvalid)
|
||
* - list (String|Array): rule name or list of rule names to disable.
|
||
* - ignoreInvalid (Boolean): set `true` to ignore errors when rule not found.
|
||
*
|
||
* The same as [[MarkdownIt.enable]], but turn specified rules off.
|
||
**/
|
||
MarkdownIt.prototype.disable = function (list, ignoreInvalid) {
|
||
var result = [];
|
||
|
||
if (!Array.isArray(list)) { list = [ list ]; }
|
||
|
||
[ 'core', 'block', 'inline' ].forEach(function (chain) {
|
||
result = result.concat(this[chain].ruler.disable(list, true));
|
||
}, this);
|
||
|
||
result = result.concat(this.inline.ruler2.disable(list, true));
|
||
|
||
var missed = list.filter(function (name) { return result.indexOf(name) < 0; });
|
||
|
||
if (missed.length && !ignoreInvalid) {
|
||
throw new Error('MarkdownIt. Failed to disable unknown rule(s): ' + missed);
|
||
}
|
||
return this;
|
||
};
|
||
|
||
|
||
/** chainable
|
||
* MarkdownIt.use(plugin, params)
|
||
*
|
||
* Load specified plugin with given params into current parser instance.
|
||
* It's just a sugar to call `plugin(md, params)` with curring.
|
||
*
|
||
* ##### Example
|
||
*
|
||
* ```javascript
|
||
* var iterator = require('markdown-it-for-inline');
|
||
* var md = require('markdown-it')()
|
||
* .use(iterator, 'foo_replace', 'text', function (tokens, idx) {
|
||
* tokens[idx].content = tokens[idx].content.replace(/foo/g, 'bar');
|
||
* });
|
||
* ```
|
||
**/
|
||
MarkdownIt.prototype.use = function (plugin /*, params, ... */) {
|
||
var args = [ this ].concat(Array.prototype.slice.call(arguments, 1));
|
||
plugin.apply(plugin, args);
|
||
return this;
|
||
};
|
||
|
||
|
||
/** internal
|
||
* MarkdownIt.parse(src, env) -> Array
|
||
* - src (String): source string
|
||
* - env (Object): environment sandbox
|
||
*
|
||
* Parse input string and return list of block tokens (special token type
|
||
* "inline" will contain list of inline tokens). You should not call this
|
||
* method directly, until you write custom renderer (for example, to produce
|
||
* AST).
|
||
*
|
||
* `env` is used to pass data between "distributed" rules and return additional
|
||
* metadata like reference info, needed for the renderer. It also can be used to
|
||
* inject data in specific cases. Usually, you will be ok to pass `{}`,
|
||
* and then pass updated object to renderer.
|
||
**/
|
||
MarkdownIt.prototype.parse = function (src, env) {
|
||
if (typeof src !== 'string') {
|
||
throw new Error('Input data should be a String');
|
||
}
|
||
|
||
var state = new this.core.State(src, this, env);
|
||
|
||
this.core.process(state);
|
||
|
||
return state.tokens;
|
||
};
|
||
|
||
|
||
/**
|
||
* MarkdownIt.render(src [, env]) -> String
|
||
* - src (String): source string
|
||
* - env (Object): environment sandbox
|
||
*
|
||
* Render markdown string into html. It does all magic for you :).
|
||
*
|
||
* `env` can be used to inject additional metadata (`{}` by default).
|
||
* But you will not need it with high probability. See also comment
|
||
* in [[MarkdownIt.parse]].
|
||
**/
|
||
MarkdownIt.prototype.render = function (src, env) {
|
||
env = env || {};
|
||
|
||
return this.renderer.render(this.parse(src, env), this.options, env);
|
||
};
|
||
|
||
|
||
/** internal
|
||
* MarkdownIt.parseInline(src, env) -> Array
|
||
* - src (String): source string
|
||
* - env (Object): environment sandbox
|
||
*
|
||
* The same as [[MarkdownIt.parse]] but skip all block rules. It returns the
|
||
* block tokens list with the single `inline` element, containing parsed inline
|
||
* tokens in `children` property. Also updates `env` object.
|
||
**/
|
||
MarkdownIt.prototype.parseInline = function (src, env) {
|
||
var state = new this.core.State(src, this, env);
|
||
|
||
state.inlineMode = true;
|
||
this.core.process(state);
|
||
|
||
return state.tokens;
|
||
};
|
||
|
||
|
||
/**
|
||
* MarkdownIt.renderInline(src [, env]) -> String
|
||
* - src (String): source string
|
||
* - env (Object): environment sandbox
|
||
*
|
||
* Similar to [[MarkdownIt.render]] but for single paragraph content. Result
|
||
* will NOT be wrapped into `<p>` tags.
|
||
**/
|
||
MarkdownIt.prototype.renderInline = function (src, env) {
|
||
env = env || {};
|
||
|
||
return this.renderer.render(this.parseInline(src, env), this.options, env);
|
||
};
|
||
|
||
|
||
var lib = MarkdownIt;
|
||
|
||
var markdownIt = lib;
|
||
|
||
// constructor
|
||
|
||
function DFA$1() {
|
||
// alphabets are encoded by numbers in 16^N form, presenting its precedence
|
||
this.__highest_alphabet__ = 0x0;
|
||
this.__match_alphabets__ = {};
|
||
// states are union (bitwise OR) of its accepted alphabets
|
||
this.__initial_state__ = 0x0;
|
||
this.__accept_states__ = {};
|
||
// transitions are in the form: {prev_state: {alphabet: next_state}}
|
||
this.__transitions__ = {};
|
||
// actions take two parameters: step (line number), prev_state and alphabet
|
||
this.__actions__ = {};
|
||
}
|
||
|
||
// setters
|
||
|
||
DFA$1.prototype.set_highest_alphabet = function (alphabet) {
|
||
this.__highest_alphabet__ = alphabet;
|
||
};
|
||
|
||
DFA$1.prototype.set_match_alphabets = function (matches) {
|
||
this.__match_alphabets__ = matches;
|
||
};
|
||
|
||
DFA$1.prototype.set_initial_state = function (initial) {
|
||
this.__initial_state__ = initial;
|
||
};
|
||
|
||
DFA$1.prototype.set_accept_states = function (accepts) {
|
||
for (var i = 0; i < accepts.length; i++) {
|
||
this.__accept_states__[accepts[i]] = true;
|
||
}
|
||
};
|
||
|
||
DFA$1.prototype.set_transitions = function (transitions) {
|
||
this.__transitions__ = transitions;
|
||
};
|
||
|
||
DFA$1.prototype.set_actions = function (actions) {
|
||
this.__actions__ = actions;
|
||
};
|
||
|
||
DFA$1.prototype.update_transition = function (state, alphabets) {
|
||
this.__transitions__[state] = Object.assign(
|
||
this.__transitions__[state] || Object(), alphabets
|
||
);
|
||
};
|
||
|
||
// methods
|
||
|
||
DFA$1.prototype.execute = function (start, end) {
|
||
var state, step, alphabet;
|
||
for (state = this.__initial_state__, step = start; state && step < end; step++) {
|
||
for (alphabet = this.__highest_alphabet__; alphabet > 0x0; alphabet >>= 4) {
|
||
if ((state & alphabet)
|
||
&& this.__match_alphabets__[alphabet].call(this, step, state, alphabet)) { break; }
|
||
}
|
||
|
||
this.__actions__(step, state, alphabet);
|
||
|
||
if (alphabet === 0x0) { break; }
|
||
state = this.__transitions__[state][alphabet] || 0x0;
|
||
}
|
||
return !!this.__accept_states__[state];
|
||
};
|
||
|
||
var dfa = DFA$1;
|
||
|
||
var DFA = dfa;
|
||
|
||
var markdownItMultimdTable = function multimd_table_plugin(md, options) {
|
||
var defaults = {
|
||
multiline: false,
|
||
rowspan: false,
|
||
headerless: false,
|
||
multibody: true
|
||
};
|
||
options = md.utils.assign({}, defaults, options || {});
|
||
|
||
function scan_bound_indices(state, line) {
|
||
/**
|
||
* Naming convention of positional variables
|
||
* - list-item
|
||
* ·········longtext······\n
|
||
* ^head ^start ^end ^max
|
||
*/
|
||
var start = state.bMarks[line] + state.sCount[line],
|
||
head = state.bMarks[line] + state.blkIndent,
|
||
end = state.skipSpacesBack(state.eMarks[line], head),
|
||
bounds = [], pos, posjump,
|
||
escape = false, code = false;
|
||
|
||
/* Scan for valid pipe character position */
|
||
for (pos = start; pos < end; pos++) {
|
||
switch (state.src.charCodeAt(pos)) {
|
||
case 0x5c /* \ */:
|
||
escape = true; break;
|
||
case 0x60 /* ` */:
|
||
posjump = state.skipChars(pos, 0x60) - 1;
|
||
/* make \` closes the code sequence, but not open it;
|
||
the reason is that `\` is correct code block */
|
||
/* eslint-disable-next-line brace-style */
|
||
if (posjump > pos) { pos = posjump; }
|
||
else if (code || !escape) { code = !code; }
|
||
escape = false; break;
|
||
case 0x7c /* | */:
|
||
if (!code && !escape) { bounds.push(pos); }
|
||
escape = false; break;
|
||
default:
|
||
escape = false; break;
|
||
}
|
||
}
|
||
if (bounds.length === 0) return bounds;
|
||
|
||
/* Pad in newline characters on last and this line */
|
||
if (bounds[0] > head) { bounds.unshift(head - 1); }
|
||
if (bounds[bounds.length - 1] < end - 1) { bounds.push(end); }
|
||
|
||
return bounds;
|
||
}
|
||
|
||
function table_caption(state, silent, line) {
|
||
var meta = { text: null, label: null },
|
||
start = state.bMarks[line] + state.sCount[line],
|
||
max = state.eMarks[line],
|
||
capRE = /^\[([^\[\]]+)\](\[([^\[\]]+)\])?\s*$/,
|
||
matches = state.src.slice(start, max).match(capRE);
|
||
|
||
if (!matches) { return false; }
|
||
if (silent) { return true; }
|
||
// TODO eliminate capRE by simple checking
|
||
|
||
meta.text = matches[1];
|
||
meta.label = matches[2] || matches[1];
|
||
meta.label = meta.label.toLowerCase().replace(/\W+/g, '');
|
||
|
||
return meta;
|
||
}
|
||
|
||
function table_row(state, silent, line) {
|
||
var meta = { bounds: null, multiline: null },
|
||
bounds = scan_bound_indices(state, line),
|
||
start, pos, oldMax;
|
||
|
||
if (bounds.length < 2) { return false; }
|
||
if (silent) { return true; }
|
||
|
||
meta.bounds = bounds;
|
||
|
||
/* Multiline. Scan boundaries again since it's very complicated */
|
||
if (options.multiline) {
|
||
start = state.bMarks[line] + state.sCount[line];
|
||
pos = state.eMarks[line] - 1; /* where backslash should be */
|
||
meta.multiline = (state.src.charCodeAt(pos) === 0x5C/* \ */);
|
||
if (meta.multiline) {
|
||
oldMax = state.eMarks[line];
|
||
state.eMarks[line] = state.skipSpacesBack(pos, start);
|
||
meta.bounds = scan_bound_indices(state, line);
|
||
state.eMarks[line] = oldMax;
|
||
}
|
||
}
|
||
|
||
return meta;
|
||
}
|
||
|
||
function table_separator(state, silent, line) {
|
||
var meta = { aligns: [], wraps: [] },
|
||
bounds = scan_bound_indices(state, line),
|
||
sepRE = /^:?(-+|=+):?\+?$/,
|
||
c, text, align;
|
||
|
||
/* Only separator needs to check indents */
|
||
if (state.sCount[line] - state.blkIndent >= 4) { return false; }
|
||
if (bounds.length === 0) { return false; }
|
||
|
||
for (c = 0; c < bounds.length - 1; c++) {
|
||
text = state.src.slice(bounds[c] + 1, bounds[c + 1]).trim();
|
||
if (!sepRE.test(text)) { return false; }
|
||
|
||
meta.wraps.push(text.charCodeAt(text.length - 1) === 0x2B/* + */);
|
||
align = ((text.charCodeAt(0) === 0x3A/* : */) << 4) |
|
||
(text.charCodeAt(text.length - 1 - meta.wraps[c]) === 0x3A);
|
||
switch (align) {
|
||
case 0x00: meta.aligns.push(''); break;
|
||
case 0x01: meta.aligns.push('right'); break;
|
||
case 0x10: meta.aligns.push('left'); break;
|
||
case 0x11: meta.aligns.push('center'); break;
|
||
}
|
||
}
|
||
if (silent) { return true; }
|
||
return meta;
|
||
}
|
||
|
||
function table_empty(state, silent, line) {
|
||
return state.isEmpty(line);
|
||
}
|
||
|
||
function table(state, startLine, endLine, silent) {
|
||
/**
|
||
* Regex pseudo code for table:
|
||
* caption? header+ separator (data+ empty)* data+ caption?
|
||
*
|
||
* We use DFA to emulate this plugin. Types with lower precedence are
|
||
* set-minus from all the formers. Noted that separator should have higher
|
||
* precedence than header or data.
|
||
* | state | caption separator header data empty | --> lower precedence
|
||
* | 0x10100 | 1 0 1 0 0 |
|
||
*/
|
||
var tableDFA = new DFA(),
|
||
grp = 0x10, mtr = -1,
|
||
token, tableToken, trToken,
|
||
colspan, leftToken,
|
||
rowspan, upTokens = [],
|
||
tableLines, tgroupLines,
|
||
tag, text, range, r, c, b;
|
||
|
||
if (startLine + 2 > endLine) { return false; }
|
||
|
||
/**
|
||
* First pass: validate and collect info into table token. IR is stored in
|
||
* markdown-it `token.meta` to be pushed later. table/tr open tokens are
|
||
* generated here.
|
||
*/
|
||
tableToken = new state.Token('table_open', 'table', 1);
|
||
tableToken.meta = { sep: null, cap: null, tr: [] };
|
||
|
||
tableDFA.set_highest_alphabet(0x10000);
|
||
tableDFA.set_initial_state(0x10100);
|
||
tableDFA.set_accept_states([ 0x10010, 0x10011, 0x00000 ]);
|
||
tableDFA.set_match_alphabets({
|
||
0x10000: table_caption.bind(this, state, true),
|
||
0x01000: table_separator.bind(this, state, true),
|
||
0x00100: table_row.bind(this, state, true),
|
||
0x00010: table_row.bind(this, state, true),
|
||
0x00001: table_empty.bind(this, state, true)
|
||
});
|
||
tableDFA.set_transitions({
|
||
0x10100: { 0x10000: 0x00100, 0x00100: 0x01100 },
|
||
0x00100: { 0x00100: 0x01100 },
|
||
0x01100: { 0x01000: 0x10010, 0x00100: 0x01100 },
|
||
0x10010: { 0x10000: 0x00000, 0x00010: 0x10011 },
|
||
0x10011: { 0x10000: 0x00000, 0x00010: 0x10011, 0x00001: 0x10010 }
|
||
});
|
||
if (options.headerless) {
|
||
tableDFA.set_initial_state(0x11100);
|
||
tableDFA.update_transition(0x11100,
|
||
{ 0x10000: 0x01100, 0x01000: 0x10010, 0x00100: 0x01100 }
|
||
);
|
||
trToken = new state.Token('tr_placeholder', 'tr', 0);
|
||
trToken.meta = Object(); // avoid trToken.meta.grp throws exception
|
||
}
|
||
if (!options.multibody) {
|
||
tableDFA.update_transition(0x10010,
|
||
{ 0x10000: 0x00000, 0x00010: 0x10010 } // 0x10011 is never reached
|
||
);
|
||
}
|
||
/* Don't mix up DFA `_state` and markdown-it `state` */
|
||
tableDFA.set_actions(function (_line, _state, _type) {
|
||
// console.log(_line, _state.toString(16), _type.toString(16)) // for test
|
||
switch (_type) {
|
||
case 0x10000:
|
||
if (tableToken.meta.cap) { break; }
|
||
tableToken.meta.cap = table_caption(state, false, _line);
|
||
tableToken.meta.cap.map = [ _line, _line + 1 ];
|
||
tableToken.meta.cap.first = (_line === startLine);
|
||
break;
|
||
case 0x01000:
|
||
tableToken.meta.sep = table_separator(state, false, _line);
|
||
tableToken.meta.sep.map = [ _line, _line + 1 ];
|
||
trToken.meta.grp |= 0x01; // previously assigned at case 0x00110
|
||
grp = 0x10;
|
||
break;
|
||
case 0x00100:
|
||
case 0x00010:
|
||
trToken = new state.Token('tr_open', 'tr', 1);
|
||
trToken.map = [ _line, _line + 1 ];
|
||
trToken.meta = table_row(state, false, _line);
|
||
trToken.meta.type = _type;
|
||
trToken.meta.grp = grp;
|
||
grp = 0x00;
|
||
tableToken.meta.tr.push(trToken);
|
||
/* Multiline. Merge trTokens as an entire multiline trToken */
|
||
if (options.multiline) {
|
||
if (trToken.meta.multiline && mtr < 0) {
|
||
/* Start line of multiline row. mark this trToken */
|
||
mtr = tableToken.meta.tr.length - 1;
|
||
} else if (!trToken.meta.multiline && mtr >= 0) {
|
||
/* End line of multiline row. merge forward until the marked trToken */
|
||
token = tableToken.meta.tr[mtr];
|
||
token.meta.mbounds = tableToken.meta.tr
|
||
.slice(mtr).map(function (tk) { return tk.meta.bounds; });
|
||
token.map[1] = trToken.map[1];
|
||
tableToken.meta.tr = tableToken.meta.tr.slice(0, mtr + 1);
|
||
mtr = -1;
|
||
}
|
||
}
|
||
break;
|
||
case 0x00001:
|
||
trToken.meta.grp |= 0x01;
|
||
grp = 0x10;
|
||
break;
|
||
}
|
||
});
|
||
|
||
if (tableDFA.execute(startLine, endLine) === false) { return false; }
|
||
// if (!tableToken.meta.sep) { return false; } // always evaluated true
|
||
if (!tableToken.meta.tr.length) { return false; } // false under headerless corner case
|
||
if (silent) { return true; }
|
||
|
||
/* Last data row cannot be detected. not stored to trToken outside? */
|
||
tableToken.meta.tr[tableToken.meta.tr.length - 1].meta.grp |= 0x01;
|
||
|
||
|
||
/**
|
||
* Second pass: actually push the tokens into `state.tokens`.
|
||
* thead/tbody/th/td open tokens and all closed tokens are generated here;
|
||
* thead/tbody are generally called tgroup; td/th are generally called tcol.
|
||
*/
|
||
tableToken.map = tableLines = [ startLine, 0 ];
|
||
tableToken.block = true;
|
||
tableToken.level = state.level++;
|
||
state.tokens.push(tableToken);
|
||
|
||
if (tableToken.meta.cap) {
|
||
token = state.push('caption_open', 'caption', 1);
|
||
token.map = tableToken.meta.cap.map;
|
||
token.attrs = [ [ 'id', tableToken.meta.cap.label ] ];
|
||
|
||
token = state.push('inline', '', 0);
|
||
token.content = tableToken.meta.cap.text;
|
||
token.map = tableToken.meta.cap.map;
|
||
token.children = [];
|
||
|
||
token = state.push('caption_close', 'caption', -1);
|
||
}
|
||
|
||
for (r = 0; r < tableToken.meta.tr.length; r++) {
|
||
leftToken = new state.Token('td_th_placeholder', '', 0);
|
||
|
||
/* Push in thead/tbody and tr open tokens */
|
||
trToken = tableToken.meta.tr[r];
|
||
// console.log(trToken.meta); // for test
|
||
if (trToken.meta.grp & 0x10) {
|
||
tag = (trToken.meta.type === 0x00100) ? 'thead' : 'tbody';
|
||
token = state.push(tag + '_open', tag, 1);
|
||
token.map = tgroupLines = [ trToken.map[0], 0 ]; // array ref
|
||
upTokens = [];
|
||
}
|
||
trToken.block = true;
|
||
trToken.level = state.level++;
|
||
state.tokens.push(trToken);
|
||
|
||
/* Push in th/td tokens */
|
||
for (c = 0; c < trToken.meta.bounds.length - 1; c++) {
|
||
range = [ trToken.meta.bounds[c] + 1, trToken.meta.bounds[c + 1] ];
|
||
text = state.src.slice.apply(state.src, range);
|
||
|
||
if (text === '') {
|
||
colspan = leftToken.attrGet('colspan');
|
||
leftToken.attrSet('colspan', colspan === null ? 2 : colspan + 1);
|
||
continue;
|
||
}
|
||
if (options.rowspan && upTokens[c] && text.trim() === '^^') {
|
||
rowspan = upTokens[c].attrGet('rowspan');
|
||
upTokens[c].attrSet('rowspan', rowspan === null ? 2 : rowspan + 1);
|
||
leftToken = new state.Token('td_th_placeholder', '', 0);
|
||
continue;
|
||
}
|
||
|
||
tag = (trToken.meta.type === 0x00100) ? 'th' : 'td';
|
||
token = state.push(tag + '_open', tag, 1);
|
||
token.map = trToken.map;
|
||
token.attrs = [];
|
||
if (tableToken.meta.sep.aligns[c]) {
|
||
token.attrs.push([ 'style', 'text-align:' + tableToken.meta.sep.aligns[c] ]);
|
||
}
|
||
if (tableToken.meta.sep.wraps[c]) {
|
||
token.attrs.push([ 'class', 'extend' ]);
|
||
}
|
||
|
||
leftToken = upTokens[c] = token;
|
||
|
||
/* Multiline. Join the text and feed into markdown-it blockParser. */
|
||
if (options.multiline && trToken.meta.multiline && trToken.meta.mbounds) {
|
||
text = [ text.trimRight() ];
|
||
for (b = 1; b < trToken.meta.mbounds.length; b++) {
|
||
/* Line with N bounds has cells indexed from 0 to N-2 */
|
||
if (c > trToken.meta.mbounds[b].length - 2) { continue; }
|
||
range = [ trToken.meta.mbounds[b][c] + 1, trToken.meta.mbounds[b][c + 1] ];
|
||
text.push(state.src.slice.apply(state.src, range).trimRight());
|
||
}
|
||
state.md.block.parse(text.join('\n'), state.md, state.env, state.tokens);
|
||
} else {
|
||
token = state.push('inline', '', 0);
|
||
token.content = text.trim();
|
||
token.map = trToken.map;
|
||
token.children = [];
|
||
}
|
||
|
||
token = state.push(tag + '_close', tag, -1);
|
||
}
|
||
|
||
/* Push in tr and thead/tbody closed tokens */
|
||
state.push('tr_close', 'tr', -1);
|
||
if (trToken.meta.grp & 0x01) {
|
||
tag = (trToken.meta.type === 0x00100) ? 'thead' : 'tbody';
|
||
token = state.push(tag + '_close', tag, -1);
|
||
tgroupLines[1] = trToken.map[1];
|
||
}
|
||
}
|
||
|
||
tableLines[1] = Math.max(
|
||
tgroupLines[1],
|
||
tableToken.meta.sep.map[1],
|
||
tableToken.meta.cap ? tableToken.meta.cap.map[1] : -1
|
||
);
|
||
token = state.push('table_close', 'table', -1);
|
||
|
||
state.line = tableLines[1];
|
||
return true;
|
||
}
|
||
|
||
md.block.ruler.at('table', table, { alt: [ 'paragraph', 'reference' ] });
|
||
};
|
||
|
||
const DEFAULT_SETTINGS = {
|
||
handleNativeTable: false,
|
||
hackPDF: false,
|
||
};
|
||
class TableExtendedSettingTab extends obsidian.PluginSettingTab {
|
||
constructor(app, plugin) {
|
||
super(app, plugin);
|
||
this.plugin = plugin;
|
||
}
|
||
display() {
|
||
this.containerEl.empty();
|
||
new obsidian.Setting(this.containerEl)
|
||
.setName("Expermental: Extended Native Table Syntax")
|
||
.setDesc(createFragment((descEl) => {
|
||
descEl.appendText("Use extended syntax on all native tables");
|
||
descEl.appendChild(createEl("br"));
|
||
descEl.appendText("Some table features may be broken, if found any, please open new issue in ");
|
||
descEl.appendChild(createEl("a", {
|
||
text: "here",
|
||
attr: {
|
||
href: "https://github.com/alx-plugins/table-extended/issues",
|
||
},
|
||
}));
|
||
}))
|
||
.addToggle((toggle) => toggle
|
||
.setValue(this.plugin.settings.handleNativeTable)
|
||
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
||
this.plugin.settings.handleNativeTable = value;
|
||
if (value)
|
||
obsidian.MarkdownPreviewRenderer.registerPostProcessor(this.plugin.processNativeTable);
|
||
else
|
||
obsidian.MarkdownPreviewRenderer.unregisterPostProcessor(this.plugin.processNativeTable);
|
||
this.plugin.refresh();
|
||
this.plugin.saveData(this.plugin.settings);
|
||
this.display();
|
||
})));
|
||
new obsidian.Setting(this.containerEl)
|
||
.setName("Expermental: Export to PDF support")
|
||
.setDesc(createFragment((descEl) => {
|
||
descEl.appendText("Reload obsidian to take effect");
|
||
descEl.appendChild(createEl("br"));
|
||
descEl.appendText("If PDF export is broken with this option enabled, disable this feature and open new issue in ");
|
||
descEl.appendChild(createEl("a", {
|
||
text: "here",
|
||
attr: {
|
||
href: "https://github.com/alx-plugins/table-extended/issues",
|
||
},
|
||
}));
|
||
}))
|
||
.addToggle((toggle) => toggle
|
||
.setValue(this.plugin.settings.hackPDF)
|
||
.onChange((value) => __awaiter(this, void 0, void 0, function* () {
|
||
this.plugin.settings.hackPDF = value;
|
||
this.plugin.saveData(this.plugin.settings);
|
||
this.display();
|
||
})));
|
||
}
|
||
}
|
||
|
||
function around(obj, factories) {
|
||
const removers = Object.keys(factories).map(key => around1(obj, key, factories[key]));
|
||
return removers.length === 1 ? removers[0] : function () { removers.forEach(r => r()); };
|
||
}
|
||
function around1(obj, method, createWrapper) {
|
||
const original = obj[method], hadOwn = obj.hasOwnProperty(method);
|
||
let current = createWrapper(original);
|
||
// Let our wrapper inherit static props from the wrapping method,
|
||
// and the wrapping method, props from the original method
|
||
if (original)
|
||
Object.setPrototypeOf(current, original);
|
||
Object.setPrototypeOf(wrapper, current);
|
||
obj[method] = wrapper;
|
||
// Return a callback to allow safe removal
|
||
return remove;
|
||
function wrapper(...args) {
|
||
// If we have been deactivated and are no longer wrapped, remove ourselves
|
||
if (current === original && obj[method] === wrapper)
|
||
remove();
|
||
return current.apply(this, args);
|
||
}
|
||
function remove() {
|
||
// If no other patches, just do a direct removal
|
||
if (obj[method] === wrapper) {
|
||
if (hadOwn)
|
||
obj[method] = original;
|
||
else
|
||
delete obj[method];
|
||
}
|
||
if (current === original)
|
||
return;
|
||
// Else pass future calls through, and remove wrapper from the prototype chain
|
||
current = original;
|
||
Object.setPrototypeOf(wrapper, original || Function);
|
||
}
|
||
}
|
||
|
||
const Export2PDFHack = (plugin) => {
|
||
const unloaders = [
|
||
around(obsidian.MarkdownView.prototype, {
|
||
// eslint-disable-next-line prefer-arrow/prefer-arrow-functions
|
||
printToPdf: (original) => function () {
|
||
plugin.print2pdfFileCache = this.file;
|
||
// shalow copy the file to provide basic info
|
||
this.file = Object.assign(Object.assign({}, this.file), { export2pdf: true });
|
||
original.call(this);
|
||
this.file = plugin.print2pdfFileCache;
|
||
},
|
||
}),
|
||
around(obsidian.Vault.prototype, {
|
||
cachedRead: (original) => function (input) {
|
||
var _a;
|
||
return __awaiter(this, void 0, void 0, function* () {
|
||
if (!(input instanceof obsidian.TFile) && ((_a = input) === null || _a === void 0 ? void 0 : _a.export2pdf)) {
|
||
const file = plugin.print2pdfFileCache;
|
||
if (!file) {
|
||
throw new Error("Failed to get file from table extended plugin instance");
|
||
}
|
||
return preprocessMarkdown(yield original.call(this, file), plugin);
|
||
}
|
||
else {
|
||
return original.call(this, input);
|
||
}
|
||
});
|
||
},
|
||
}),
|
||
];
|
||
unloaders.forEach((u) => plugin.register(u));
|
||
};
|
||
/**
|
||
* warp all tables in markdown text with tx codeblock
|
||
*/
|
||
const preprocessMarkdown = (text, plugin) => {
|
||
if (!text)
|
||
return text;
|
||
const ast = plugin.mdit.parse(text, {});
|
||
let tableStarts = [], tableEnds = [];
|
||
let linesToRemove = [];
|
||
ast.forEach((token, index, allTokens) => {
|
||
if (token.type === "table_open") {
|
||
let txTable = false;
|
||
if (index - 3 >= 0) {
|
||
const paraStart = index - 3, paraContent = index - 2;
|
||
if (allTokens[paraStart].type === "paragraph_open" &&
|
||
allTokens[paraContent].type === "inline" &&
|
||
allTokens[paraContent].content === "-tx-") {
|
||
// remove -tx- prefix
|
||
linesToRemove.push(token.map[0] - 1);
|
||
txTable = true;
|
||
}
|
||
}
|
||
// process all tables or only tables with -tx- prefix
|
||
if (plugin.settings.handleNativeTable || txTable) {
|
||
tableStarts.push(token.map[0]);
|
||
tableEnds.push(token.map[1]);
|
||
}
|
||
}
|
||
});
|
||
if (tableStarts.length === 0)
|
||
return text;
|
||
let lines = text.split(/\r?\n/).flatMap((line, index) => {
|
||
// remove -tx- prefix
|
||
if (linesToRemove.includes(index))
|
||
return [];
|
||
// warp all tables with tx codeblock
|
||
if (tableStarts.includes(index))
|
||
return ["```tx", line];
|
||
if (tableEnds.includes(index))
|
||
return ["```", line];
|
||
return [line];
|
||
});
|
||
return lines.join("\n");
|
||
};
|
||
|
||
const mditOptions = { html: true };
|
||
const elToPreserveText = ["td", "th", "caption"];
|
||
/**
|
||
* process ast to extract source markdown text from table cells
|
||
* @param ast ids are added for each table cell
|
||
* @returns array of markdown text, with index being part of id for corresponding cell element
|
||
*/
|
||
const processAST = (ast) => {
|
||
let srcMarkdown = [];
|
||
for (let i = 0; i < ast.length; i++) {
|
||
const token = ast[i];
|
||
if (elToPreserveText.includes(token.tag) && token.nesting === 1) {
|
||
let iInline = i, nextToken = ast[++iInline];
|
||
while (
|
||
// not closing tag
|
||
!elToPreserveText.includes(nextToken.tag) ||
|
||
nextToken.nesting !== -1) {
|
||
let content = "";
|
||
if (nextToken.type === "inline") {
|
||
content = nextToken.content;
|
||
}
|
||
else if (nextToken.type === "fence") {
|
||
content =
|
||
"```" + nextToken.info + "\n" + nextToken.content + "\n" + "```";
|
||
}
|
||
else if (nextToken.type === "code_block") {
|
||
content = nextToken.content.replace(/^/gm, " ");
|
||
}
|
||
if (content) {
|
||
const index = srcMarkdown.push(content) - 1;
|
||
token.attrSet("id", `TX_${index}`);
|
||
break;
|
||
}
|
||
nextToken = ast[++iInline];
|
||
}
|
||
// skip inline token and close token
|
||
i = iInline;
|
||
}
|
||
}
|
||
return srcMarkdown;
|
||
};
|
||
// eslint-disable-next-line prefer-arrow/prefer-arrow-functions
|
||
function renderMarkdown(src, blockEl, ctx) {
|
||
let child = new obsidian.MarkdownRenderChild(blockEl);
|
||
ctx.addChild(child);
|
||
// import render results
|
||
const ast = this.mdit.parse(src, {}), MarkdownTextInTable = processAST(ast);
|
||
const result = this.mdit.renderer.render(ast, mditOptions, {});
|
||
blockEl.innerHTML = result;
|
||
for (let el of blockEl.querySelectorAll("[id^=TX_]")) {
|
||
const parent = el, indexText = el.id.substring(3 /* "TX_".length */);
|
||
el.removeAttribute("id");
|
||
if (!Number.isInteger(+indexText))
|
||
continue;
|
||
const text = MarkdownTextInTable[+indexText];
|
||
if (!text)
|
||
continue;
|
||
parent.empty();
|
||
obsidian.MarkdownRenderer.renderMarkdown(text, parent, ctx.sourcePath, child);
|
||
let renderedFirstBlock = parent.firstElementChild;
|
||
if (renderedFirstBlock) {
|
||
const from = renderedFirstBlock;
|
||
// copy attr set in markdown-attribute
|
||
["style", "class", "id"].forEach((attr) => copyAttr(attr, from, parent));
|
||
if (renderedFirstBlock instanceof HTMLElement) {
|
||
Object.assign(parent.dataset, renderedFirstBlock.dataset);
|
||
}
|
||
// unwarp all children to the parent table cell/caption
|
||
if (renderedFirstBlock instanceof HTMLParagraphElement)
|
||
renderedFirstBlock.replaceWith(...renderedFirstBlock.childNodes);
|
||
}
|
||
}
|
||
}
|
||
const copyAttr = (attr, from, to) => {
|
||
if (from.hasAttribute(attr)) {
|
||
to.setAttribute(attr, from.getAttribute(attr));
|
||
}
|
||
};
|
||
|
||
const prefixPatternInMD = /^(?:>\s*)?-tx-\n/;
|
||
class TableExtended extends obsidian.Plugin {
|
||
constructor(...args) {
|
||
super(...args);
|
||
this.settings = DEFAULT_SETTINGS;
|
||
this.print2pdfFileCache = null;
|
||
this.processNativeTable = (el, ctx) => {
|
||
if (!el.querySelector("table"))
|
||
return;
|
||
const raw = getSourceMarkdown(el, ctx);
|
||
if (!raw) {
|
||
console.warn("failed to get Markdown text, escaping...");
|
||
return;
|
||
}
|
||
el.empty();
|
||
this.renderFromMD(raw, el, ctx);
|
||
};
|
||
this.processTextSection = (el, ctx) => {
|
||
// el contains only els for one block in preview;
|
||
// el contains els for all blocks in export2pdf
|
||
for (const child of el.children) {
|
||
let p;
|
||
if (child instanceof HTMLParagraphElement) {
|
||
p = child;
|
||
}
|
||
else if (child instanceof HTMLQuoteElement &&
|
||
child.firstElementChild instanceof HTMLParagraphElement) {
|
||
p = child.firstElementChild;
|
||
}
|
||
else
|
||
continue;
|
||
let result;
|
||
if (p.innerHTML.startsWith("-tx-")) {
|
||
const src = getSourceMarkdown(el, ctx);
|
||
if (!src) {
|
||
console.warn("failed to get Markdown text, escaping...");
|
||
}
|
||
else if ((result = src.match(prefixPatternInMD))) {
|
||
const footnoteSelector = "sup.footnote-ref";
|
||
// save footnote refs
|
||
const footnoteRefs = [
|
||
...el.querySelectorAll(footnoteSelector),
|
||
];
|
||
// footnote refs is replaced by new ones during rendering
|
||
this.renderFromMD(src.substring(result[0].length), el, ctx);
|
||
// post process to revert footnote refs
|
||
for (const newRefs of el.querySelectorAll(footnoteSelector)) {
|
||
newRefs.replaceWith(footnoteRefs.shift());
|
||
}
|
||
for (const fnSection of el.querySelectorAll("section.footnotes")) {
|
||
fnSection.remove();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
};
|
||
/** refresh opened MarkdownView */
|
||
this.refresh = () => this.app.workspace.iterateAllLeaves((leaf) => setTimeout(() => {
|
||
if (leaf.view instanceof obsidian.MarkdownView) {
|
||
leaf.view.previewMode.rerender(true);
|
||
}
|
||
}, 200));
|
||
this.renderFromMD = renderMarkdown.bind(this);
|
||
this.mdit = markdownIt(mditOptions).use(markdownItMultimdTable, {
|
||
multiline: true,
|
||
rowspan: true,
|
||
headerless: true,
|
||
});
|
||
/** keep only table required features, let obsidian handle the markdown inside cell */
|
||
this.mdit.block.ruler.enableOnly([
|
||
"code",
|
||
"fence",
|
||
"table",
|
||
"paragraph",
|
||
"reference",
|
||
"blockquote",
|
||
]);
|
||
this.mdit.inline.ruler.enableOnly([]);
|
||
}
|
||
loadSettings() {
|
||
return __awaiter(this, void 0, void 0, function* () {
|
||
this.settings = Object.assign(Object.assign({}, this.settings), (yield this.loadData()));
|
||
});
|
||
}
|
||
saveSettings() {
|
||
return __awaiter(this, void 0, void 0, function* () {
|
||
yield this.saveData(this.settings);
|
||
});
|
||
}
|
||
onload() {
|
||
return __awaiter(this, void 0, void 0, function* () {
|
||
console.log("loading table-extended");
|
||
yield this.loadSettings();
|
||
this.addSettingTab(new TableExtendedSettingTab(this.app, this));
|
||
if (this.settings.hackPDF) {
|
||
Export2PDFHack(this);
|
||
}
|
||
if (this.settings.handleNativeTable)
|
||
obsidian.MarkdownPreviewRenderer.registerPostProcessor(this.processNativeTable);
|
||
this.registerMarkdownCodeBlockProcessor("tx", this.renderFromMD);
|
||
this.registerMarkdownPostProcessor(this.processTextSection);
|
||
// Read Obsidian's config to keep "strictLineBreaks" option in sync
|
||
this.mdit.set({
|
||
breaks: !this.app.vault.getConfig("strictLineBreaks"),
|
||
});
|
||
this.app.workspace.onLayoutReady(this.refresh);
|
||
});
|
||
}
|
||
onunload() {
|
||
console.log("unloading table-extended");
|
||
obsidian.MarkdownPreviewRenderer.unregisterPostProcessor(this.processNativeTable);
|
||
this.refresh();
|
||
this.print2pdfFileCache = null;
|
||
}
|
||
}
|
||
const getSourceMarkdown = (sectionEl, ctx) => {
|
||
let info = ctx.getSectionInfo(sectionEl);
|
||
if (info) {
|
||
const { text, lineStart, lineEnd } = info;
|
||
return text
|
||
.split("\n")
|
||
.slice(lineStart, lineEnd + 1)
|
||
.join("\n");
|
||
}
|
||
else {
|
||
return null;
|
||
}
|
||
};
|
||
|
||
module.exports = TableExtended;
|
||
|
||
|
||
/* nosourcemap */ |