| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873 |
- (function () {
- /**
- * Block-Level Grammar
- */
- var block = {
- newline: /^\n+/,
- code: /^( {4}[^\n]+\n*)+/,
- fences: noop,
- hr: /^( *[-*_]){3,} *(?:\n+|$)/,
- heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
- nptable: noop,
- lheading: /^([^\n]+)\n *(=|-){3,} *\n*/,
- blockquote: /^( *>[^\n]+(\n[^\n]+)*\n*)+/,
- list: /^( *)(bull) [\s\S]+?(?:hr|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
- html: /^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/,
- def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
- table: noop,
- paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
- text: /^[^\n]+/,
- };
- block.bullet = /(?:[*+-]|\d+\.)/;
- block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
- block.item = replace(block.item, "gm")(/bull/g, block.bullet)();
- block.list = replace(block.list)(/bull/g, block.bullet)("hr", /\n+(?=(?: *[-*_]){3,} *(?:\n+|$))/)();
- block._tag =
- "(?!(?:" +
- "a|em|strong|small|s|cite|q|dfn|abbr|data|time|code" +
- "|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo" +
- "|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|@)\\b";
- block.html = replace(block.html)("comment", /<!--[\s\S]*?-->/)("closed", /<(tag)[\s\S]+?<\/\1>/)(
- "closing",
- /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/
- )(/tag/g, block._tag)();
- block.paragraph = replace(block.paragraph)("hr", block.hr)("heading", block.heading)("lheading", block.lheading)(
- "blockquote",
- block.blockquote
- )("tag", "<" + block._tag)("def", block.def)();
- /**
- * Normal Block Grammar
- */
- block.normal = merge({}, block);
- /**
- * GFM Block Grammar
- */
- block.gfm = merge({}, block.normal, {
- fences: /^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/,
- paragraph: /^/,
- });
- block.gfm.paragraph = replace(block.paragraph)(
- "(?!",
- "(?!" + block.gfm.fences.source.replace("\\1", "\\2") + "|"
- )();
- /**
- * GFM + Tables Block Grammar
- */
- block.tables = merge({}, block.gfm, {
- nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
- table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/,
- });
- /**
- * Block Lexer
- */
- function Lexer(options) {
- this.tokens = [];
- this.tokens.links = {};
- this.options = options || marked.defaults;
- this.rules = block.normal;
- if (this.options.gfm) {
- if (this.options.tables) {
- this.rules = block.tables;
- } else {
- this.rules = block.gfm;
- }
- }
- }
- /**
- * Expose Block Rules
- */
- Lexer.rules = block;
- /**
- * Static Lex Method
- */
- Lexer.lex = function (src, options) {
- var lexer = new Lexer(options);
- return lexer.lex(src);
- };
- /**
- * Preprocessing
- */
- Lexer.prototype.lex = function (src) {
- src = src
- .replace(/\r\n|\r/g, "\n")
- .replace(/\t/g, " ")
- .replace(/\u00a0/g, " ")
- .replace(/\u2424/g, "\n");
- return this.token(src, true);
- };
- /**
- * Lexing
- */
- Lexer.prototype.token = function (src, top) {
- var src = src.replace(/^ +$/gm, ""),
- next,
- loose,
- cap,
- bull,
- b,
- item,
- space,
- i,
- l;
- while (src) {
- // newline
- if ((cap = this.rules.newline.exec(src))) {
- src = src.substring(cap[0].length);
- if (cap[0].length > 1) {
- this.tokens.push({
- type: "space",
- });
- }
- }
- // code
- if ((cap = this.rules.code.exec(src))) {
- src = src.substring(cap[0].length);
- cap = cap[0].replace(/^ {4}/gm, "");
- this.tokens.push({
- type: "code",
- text: !this.options.pedantic ? cap.replace(/\n+$/, "") : cap,
- });
- continue;
- }
- // fences (gfm)
- if ((cap = this.rules.fences.exec(src))) {
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: "code",
- lang: cap[2],
- text: cap[3],
- });
- continue;
- }
- // heading
- if ((cap = this.rules.heading.exec(src))) {
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: "heading",
- depth: cap[1].length,
- text: cap[2],
- });
- continue;
- }
- // table no leading pipe (gfm)
- if (top && (cap = this.rules.nptable.exec(src))) {
- src = src.substring(cap[0].length);
- item = {
- type: "table",
- header: cap[1].replace(/^ *| *\| *$/g, "").split(/ *\| */),
- align: cap[2].replace(/^ *|\| *$/g, "").split(/ *\| */),
- cells: cap[3].replace(/\n$/, "").split("\n"),
- };
- for (i = 0; i < item.align.length; i++) {
- if (/^ *-+: *$/.test(item.align[i])) {
- item.align[i] = "right";
- } else if (/^ *:-+: *$/.test(item.align[i])) {
- item.align[i] = "center";
- } else if (/^ *:-+ *$/.test(item.align[i])) {
- item.align[i] = "left";
- } else {
- item.align[i] = null;
- }
- }
- for (i = 0; i < item.cells.length; i++) {
- item.cells[i] = item.cells[i].split(/ *\| */);
- }
- this.tokens.push(item);
- continue;
- }
- // lheading
- if ((cap = this.rules.lheading.exec(src))) {
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: "heading",
- depth: cap[2] === "=" ? 1 : 2,
- text: cap[1],
- });
- continue;
- }
- // hr
- if ((cap = this.rules.hr.exec(src))) {
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: "hr",
- });
- continue;
- }
- // blockquote
- if ((cap = this.rules.blockquote.exec(src))) {
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: "blockquote_start",
- });
- cap = cap[0].replace(/^ *> ?/gm, "");
- // Pass `top` to keep the current
- // "toplevel" state. This is exactly
- // how markdown.pl works.
- this.token(cap, top);
- this.tokens.push({
- type: "blockquote_end",
- });
- continue;
- }
- // list
- if ((cap = this.rules.list.exec(src))) {
- src = src.substring(cap[0].length);
- bull = cap[2];
- this.tokens.push({
- type: "list_start",
- ordered: bull.length > 1,
- });
- // Get each top-level item.
- cap = cap[0].match(this.rules.item);
- next = false;
- l = cap.length;
- i = 0;
- for (; i < l; i++) {
- item = cap[i];
- // Remove the list item's bullet
- // so it is seen as the next token.
- space = item.length;
- item = item.replace(/^ *([*+-]|\d+\.) +/, "");
- // Outdent whatever the
- // list item contains. Hacky.
- if (~item.indexOf("\n ")) {
- space -= item.length;
- item = !this.options.pedantic
- ? item.replace(new RegExp("^ {1," + space + "}", "gm"), "")
- : item.replace(/^ {1,4}/gm, "");
- }
- // Determine whether the next list item belongs here.
- // Backpedal if it does not belong in this list.
- if (this.options.smartLists && i !== l - 1) {
- b = block.bullet.exec(cap[i + 1])[0];
- if (bull !== b && !(bull.length > 1 && b.length > 1)) {
- src = cap.slice(i + 1).join("\n") + src;
- i = l - 1;
- }
- }
- // Determine whether item is loose or not.
- // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
- // for discount behavior.
- loose = next || /\n\n(?!\s*$)/.test(item);
- if (i !== l - 1) {
- next = item[item.length - 1] === "\n";
- if (!loose) loose = next;
- }
- this.tokens.push({
- type: loose ? "loose_item_start" : "list_item_start",
- });
- // Recurse.
- this.token(item, false);
- this.tokens.push({
- type: "list_item_end",
- });
- }
- this.tokens.push({
- type: "list_end",
- });
- continue;
- }
- // html
- if ((cap = this.rules.html.exec(src))) {
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: this.options.sanitize ? "paragraph" : "html",
- pre: cap[1] === "pre" || cap[1] === "script",
- text: cap[0],
- });
- continue;
- }
- // def
- if (top && (cap = this.rules.def.exec(src))) {
- src = src.substring(cap[0].length);
- this.tokens.links[cap[1].toLowerCase()] = {
- href: cap[2],
- title: cap[3],
- };
- continue;
- }
- // table (gfm)
- if (top && (cap = this.rules.table.exec(src))) {
- src = src.substring(cap[0].length);
- item = {
- type: "table",
- header: cap[1].replace(/^ *| *\| *$/g, "").split(/ *\| */),
- align: cap[2].replace(/^ *|\| *$/g, "").split(/ *\| */),
- cells: cap[3].replace(/(?: *\| *)?\n$/, "").split("\n"),
- };
- for (i = 0; i < item.align.length; i++) {
- if (/^ *-+: *$/.test(item.align[i])) {
- item.align[i] = "right";
- } else if (/^ *:-+: *$/.test(item.align[i])) {
- item.align[i] = "center";
- } else if (/^ *:-+ *$/.test(item.align[i])) {
- item.align[i] = "left";
- } else {
- item.align[i] = null;
- }
- }
- for (i = 0; i < item.cells.length; i++) {
- item.cells[i] = item.cells[i].replace(/^ *\| *| *\| *$/g, "").split(/ *\| */);
- }
- this.tokens.push(item);
- continue;
- }
- // top-level paragraph
- if (top && (cap = this.rules.paragraph.exec(src))) {
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: "paragraph",
- text: cap[1][cap[1].length - 1] === "\n" ? cap[1].slice(0, -1) : cap[1],
- });
- continue;
- }
- // text
- if ((cap = this.rules.text.exec(src))) {
- // Top-level should never reach here.
- src = src.substring(cap[0].length);
- this.tokens.push({
- type: "text",
- text: cap[0],
- });
- continue;
- }
- if (src) {
- throw new Error("Infinite loop on byte: " + src.charCodeAt(0));
- }
- }
- return this.tokens;
- };
- /**
- * Inline-Level Grammar
- */
- var inline = {
- escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
- autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
- url: noop,
- tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
- link: /^!?\[(inside)\]\(href\)/,
- reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
- nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
- strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
- em: /^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
- code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
- br: /^ {2,}\n(?!\s*$)/,
- del: noop,
- text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/,
- };
- inline._inside = /(?:\[[^\]]*\]|[^\]]|\](?=[^\[]*\]))*/;
- inline._href = /\s*<?(.*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
- inline.link = replace(inline.link)("inside", inline._inside)("href", inline._href)();
- inline.reflink = replace(inline.reflink)("inside", inline._inside)();
- /**
- * Normal Inline Grammar
- */
- inline.normal = merge({}, inline);
- /**
- * Pedantic Inline Grammar
- */
- inline.pedantic = merge({}, inline.normal, {
- strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
- em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/,
- });
- /**
- * GFM Inline Grammar
- */
- inline.gfm = merge({}, inline.normal, {
- escape: replace(inline.escape)("])", "~|])")(),
- url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
- del: /^~~(?=\S)([\s\S]*?\S)~~/,
- text: replace(inline.text)("]|", "~]|")("|", "|https?://|")(),
- });
- /**
- * GFM + Line Breaks Inline Grammar
- */
- inline.breaks = merge({}, inline.gfm, {
- br: replace(inline.br)("{2,}", "*")(),
- text: replace(inline.gfm.text)("{2,}", "*")(),
- });
- /**
- * Inline Lexer & Compiler
- */
- function InlineLexer(links, options) {
- this.options = options || marked.defaults;
- this.links = links;
- this.rules = inline.normal;
- if (!this.links) {
- throw new Error("Tokens array requires a `links` property.");
- }
- if (this.options.gfm) {
- if (this.options.breaks) {
- this.rules = inline.breaks;
- } else {
- this.rules = inline.gfm;
- }
- } else if (this.options.pedantic) {
- this.rules = inline.pedantic;
- }
- }
- /**
- * Expose Inline Rules
- */
- InlineLexer.rules = inline;
- /**
- * Static Lexing/Compiling Method
- */
- InlineLexer.output = function (src, links, options) {
- var inline = new InlineLexer(links, options);
- return inline.output(src);
- };
- /**
- * Lexing/Compiling
- */
- InlineLexer.prototype.output = function (src) {
- var out = "",
- link,
- text,
- href,
- cap;
- while (src) {
- // escape
- if ((cap = this.rules.escape.exec(src))) {
- src = src.substring(cap[0].length);
- out += cap[1];
- continue;
- }
- // autolink
- if ((cap = this.rules.autolink.exec(src))) {
- src = src.substring(cap[0].length);
- if (cap[2] === "@") {
- text = cap[1][6] === ":" ? this.mangle(cap[1].substring(7)) : this.mangle(cap[1]);
- href = this.mangle("mailto:") + text;
- } else {
- text = escape(cap[1]);
- href = text;
- }
- out += '<a href="' + href + '">' + text + "</a>";
- continue;
- }
- // url (gfm)
- if ((cap = this.rules.url.exec(src))) {
- src = src.substring(cap[0].length);
- text = escape(cap[1]);
- href = text;
- out += '<a href="' + href + '">' + text + "</a>";
- continue;
- }
- // tag
- if ((cap = this.rules.tag.exec(src))) {
- src = src.substring(cap[0].length);
- out += this.options.sanitize ? escape(cap[0]) : cap[0];
- continue;
- }
- // link
- if ((cap = this.rules.link.exec(src))) {
- src = src.substring(cap[0].length);
- out += this.outputLink(cap, {
- href: cap[2],
- title: cap[3],
- });
- continue;
- }
- // reflink, nolink
- if ((cap = this.rules.reflink.exec(src)) || (cap = this.rules.nolink.exec(src))) {
- src = src.substring(cap[0].length);
- link = (cap[2] || cap[1]).replace(/\s+/g, " ");
- link = this.links[link.toLowerCase()];
- if (!link || !link.href) {
- out += cap[0][0];
- src = cap[0].substring(1) + src;
- continue;
- }
- out += this.outputLink(cap, link);
- continue;
- }
- // strong
- if ((cap = this.rules.strong.exec(src))) {
- src = src.substring(cap[0].length);
- out += "<strong>" + this.output(cap[2] || cap[1]) + "</strong>";
- continue;
- }
- // em
- if ((cap = this.rules.em.exec(src))) {
- src = src.substring(cap[0].length);
- out += "<em>" + this.output(cap[2] || cap[1]) + "</em>";
- continue;
- }
- // code
- if ((cap = this.rules.code.exec(src))) {
- src = src.substring(cap[0].length);
- out += "<code>" + escape(cap[2], true) + "</code>";
- continue;
- }
- // br
- if ((cap = this.rules.br.exec(src))) {
- src = src.substring(cap[0].length);
- out += "<br>";
- continue;
- }
- // del (gfm)
- if ((cap = this.rules.del.exec(src))) {
- src = src.substring(cap[0].length);
- out += "<del>" + this.output(cap[1]) + "</del>";
- continue;
- }
- // text
- if ((cap = this.rules.text.exec(src))) {
- src = src.substring(cap[0].length);
- out += escape(cap[0]);
- continue;
- }
- if (src) {
- throw new Error("Infinite loop on byte: " + src.charCodeAt(0));
- }
- }
- return out;
- };
- /**
- * Compile Link
- */
- InlineLexer.prototype.outputLink = function (cap, link) {
- if (cap[0][0] !== "!") {
- return (
- '<a href="' +
- escape(link.href) +
- '"' +
- (link.title ? ' title="' + escape(link.title) + '"' : "") +
- ">" +
- this.output(cap[1]) +
- "</a>"
- );
- } else {
- return (
- '<img src="' +
- escape(link.href) +
- '" alt="' +
- escape(cap[1]) +
- '"' +
- (link.title ? ' title="' + escape(link.title) + '"' : "") +
- ">"
- );
- }
- };
- /**
- * Smartypants Transformations
- */
- InlineLexer.prototype.smartypants = function (text) {
- if (!this.options.smartypants) return text;
- return text
- .replace(/--/g, "—")
- .replace(/'([^']*)'/g, "‘$1’")
- .replace(/"([^"]*)"/g, "“$1”")
- .replace(/\.{3}/g, "…");
- };
- /**
- * Mangle Links
- */
- InlineLexer.prototype.mangle = function (text) {
- var out = "",
- l = text.length,
- i = 0,
- ch;
- for (; i < l; i++) {
- ch = text.charCodeAt(i);
- if (Math.random() > 0.5) {
- ch = "x" + ch.toString(16);
- }
- out += "&#" + ch + ";";
- }
- return out;
- };
- /**
- * Parsing & Compiling
- */
- function Parser(options) {
- this.tokens = [];
- this.token = null;
- this.options = options || marked.defaults;
- }
- /**
- * Static Parse Method
- */
- Parser.parse = function (src, options) {
- var parser = new Parser(options);
- return parser.parse(src);
- };
- /**
- * Parse Loop
- */
- Parser.prototype.parse = function (src) {
- this.inline = new InlineLexer(src.links, this.options);
- this.tokens = src.reverse();
- var out = "";
- while (this.next()) {
- out += this.tok();
- }
- return out;
- };
- /**
- * Next Token
- */
- Parser.prototype.next = function () {
- return (this.token = this.tokens.pop());
- };
- /**
- * Preview Next Token
- */
- Parser.prototype.peek = function () {
- return this.tokens[this.tokens.length - 1] || 0;
- };
- /**
- * Parse Text Tokens
- */
- Parser.prototype.parseText = function () {
- var body = this.token.text;
- while (this.peek().type === "text") {
- body += "\n" + this.next().text;
- }
- return this.inline.output(body);
- };
- /**
- * Parse Current Token
- */
- Parser.prototype.tok = function () {
- switch (this.token.type) {
- case "space": {
- return "";
- }
- case "hr": {
- return "<hr>\n";
- }
- case "heading": {
- return (
- "<h" +
- this.token.depth +
- ">" +
- this.inline.output(this.token.text) +
- "</h" +
- this.token.depth +
- ">\n"
- );
- }
- case "code": {
- if (this.options.highlight) {
- var code = this.options.highlight(this.token.text, this.token.lang);
- if (code != null && code !== this.token.text) {
- this.token.escaped = true;
- this.token.text = code;
- }
- }
- if (!this.token.escaped) {
- this.token.text = escape(this.token.text, true);
- }
- return (
- "<pre><code" +
- (this.token.lang ? ' class="' + this.options.langPrefix + this.token.lang + '"' : "") +
- ">" +
- this.token.text +
- "</code></pre>\n"
- );
- }
- case "table": {
- var body = "",
- heading,
- i,
- row,
- cell,
- j;
- // header
- body += "<thead>\n<tr>\n";
- for (i = 0; i < this.token.header.length; i++) {
- heading = this.inline.output(this.token.header[i]);
- body += this.token.align[i]
- ? '<th align="' + this.token.align[i] + '">' + heading + "</th>\n"
- : "<th>" + heading + "</th>\n";
- }
- body += "</tr>\n</thead>\n";
- // body
- body += "<tbody>\n";
- for (i = 0; i < this.token.cells.length; i++) {
- row = this.token.cells[i];
- body += "<tr>\n";
- for (j = 0; j < row.length; j++) {
- cell = this.inline.output(row[j]);
- body += this.token.align[j]
- ? '<td align="' + this.token.align[j] + '">' + cell + "</td>\n"
- : "<td>" + cell + "</td>\n";
- }
- body += "</tr>\n";
- }
- body += "</tbody>\n";
- return "<table>\n" + body + "</table>\n";
- }
- case "blockquote_start": {
- var body = "";
- while (this.next().type !== "blockquote_end") {
- body += this.tok();
- }
- return "<blockquote>\n" + body + "</blockquote>\n";
- }
- case "list_start": {
- var type = this.token.ordered ? "ol" : "ul",
- body = "";
- while (this.next().type !== "list_end") {
- body += this.tok();
- }
- return "<" + type + ">\n" + body + "</" + type + ">\n";
- }
- case "list_item_start": {
- var body = "";
- while (this.next().type !== "list_item_end") {
- body += this.token.type === "text" ? this.parseText() : this.tok();
- }
- return "<li>" + body + "</li>\n";
- }
- case "loose_item_start": {
- var body = "";
- while (this.next().type !== "list_item_end") {
- body += this.tok();
- }
- return "<li>" + body + "</li>\n";
- }
- case "html": {
- return !this.token.pre && !this.options.pedantic
- ? this.inline.output(this.token.text)
- : this.token.text;
- }
- case "paragraph": {
- return "<p>" + this.inline.output(this.token.text) + "</p>\n";
- }
- case "text": {
- return "<p>" + this.parseText() + "</p>\n";
- }
- }
- };
- /**
- * Helpers
- */
- function escape(html, encode) {
- return html
- .replace(!encode ? /&(?!#?\w+;)/g : /&/g, "&")
- .replace(/</g, "<")
- .replace(/>/g, ">")
- .replace(/"/g, """)
- .replace(/'/g, "'");
- }
- function replace(regex, opt) {
- regex = regex.source;
- opt = opt || "";
- return function self(name, val) {
- if (!name) return new RegExp(regex, opt);
- val = val.source || val;
- val = val.replace(/(^|[^\[])\^/g, "$1");
- regex = regex.replace(name, val);
- return self;
- };
- }
- function noop() {}
- noop.exec = noop;
- function merge(obj) {
- var i = 1,
- target,
- key;
- for (; i < arguments.length; i++) {
- target = arguments[i];
- for (key in target) {
- if (Object.prototype.hasOwnProperty.call(target, key)) {
- obj[key] = target[key];
- }
- }
- }
- return obj;
- }
- /**
- * Marked
- */
- function marked(src, opt, callback) {
- if (callback || typeof opt === "function") {
- if (!callback) {
- callback = opt;
- opt = null;
- }
- if (opt) opt = merge({}, marked.defaults, opt);
- var tokens = Lexer.lex(tokens, opt),
- highlight = opt.highlight,
- pending = 0,
- l = tokens.length,
- i = 0;
- if (!highlight || highlight.length < 3) {
- return callback(null, Parser.parse(tokens, opt));
- }
- var done = function () {
- delete opt.highlight;
- var out = Parser.parse(tokens, opt);
- opt.highlight = highlight;
- return callback(null, out);
- };
- for (; i < l; i++) {
- (function (token) {
- if (token.type !== "code") return;
- pending++;
- return highlight(token.text, token.lang, function (err, code) {
- if (code == null || code === token.text) {
- return --pending || done();
- }
- token.text = code;
- token.escaped = true;
- --pending || done();
- });
- })(tokens[i]);
- }
- return;
- }
- try {
- if (opt) opt = merge({}, marked.defaults, opt);
- return Parser.parse(Lexer.lex(src, opt), opt);
- } catch (e) {
- e.message += "\nPlease report this to https://github.com/chjj/marked.";
- if ((opt || marked.defaults).silent) {
- return "<p>An error occured:</p><pre>" + escape(e.message + "", true) + "</pre>";
- }
- throw e;
- }
- }
- /**
- * Options
- */
- marked.options = marked.setOptions = function (opt) {
- merge(marked.defaults, opt);
- return marked;
- };
- marked.defaults = {
- gfm: true,
- tables: true,
- breaks: false,
- pedantic: false,
- sanitize: false,
- smartLists: false,
- silent: false,
- highlight: null,
- langPrefix: "lang-",
- };
- /**
- * Expose
- */
- marked.Parser = Parser;
- marked.parser = Parser.parse;
- marked.Lexer = Lexer;
- marked.lexer = Lexer.lex;
- marked.InlineLexer = InlineLexer;
- marked.inlineLexer = InlineLexer.output;
- marked.parse = marked;
- if (typeof exports === "object") {
- module.exports = marked;
- } else if (typeof define === "function" && define.amd) {
- define(function () {
- return marked;
- });
- } else {
- this.marked = marked;
- }
- }).call(
- (function () {
- return this || (typeof window !== "undefined" ? window : global);
- })()
- );
- (function ($) {
- "use strict";
- // hide the whole page so we dont see the DOM flickering
- // will be shown upon page load complete or error
- $("html").addClass("md-hidden-load");
- // register our $.md object
- $.md = function (method) {
- if ($.md.publicMethods[method]) {
- return $.md.publicMethods[method].apply(this, Array.prototype.slice.call(arguments, 1));
- } else {
- $.error("Method " + method + " does not exist on jquery.md");
- }
- };
- // default config
- $.md.config = {
- title: null,
- useSideMenu: true,
- lineBreaks: "gfm",
- additionalFooterText: "",
- anchorCharacter: "¶",
- tocAnchor: "[ ↑ ]",
- };
- $.md.gimmicks = [];
- $.md.stages = [];
- // the location of the main markdown file we display
- $.md.mainHref = "";
- // the in-page anchor that is specified after the !
- $.md.inPageAnchor = "";
- $.md.loglevel = {
- TRACE: 10,
- DEBUG: 20,
- INFO: 30,
- WARN: 40,
- ERROR: 50,
- FATAL: 60,
- };
- // $.md.logThreshold = $.md.loglevel.DEBUG;
- $.md.logThreshold = $.md.loglevel.WARN;
- })(jQuery);
- (function ($) {
- "use strict";
- $.md.getLogger = function () {
- var loglevel = $.md.loglevel;
- var log = function (logtarget) {
- var self = this;
- var level = loglevel[logtarget];
- return function (msg) {
- if ($.md.logThreshold <= level) {
- console.log("[" + logtarget + "] " + msg);
- }
- };
- };
- var logger = {};
- logger.trace = log("TRACE");
- logger.debug = log("DEBUG");
- logger.info = log("INFO");
- logger.warn = log("WARN");
- logger.error = log("ERROR");
- logger.fatal = log("FATAL");
- return logger;
- };
- })(jQuery);
- (function ($) {
- "use strict";
- var log = $.md.getLogger();
- $.Stage = function (name) {
- var self = $.extend($.Deferred(), {});
- self.name = name;
- self.events = [];
- self.started = false;
- self.reset = function () {
- self.complete = $.Deferred();
- self.outstanding = [];
- };
- self.reset();
- self.subscribe = function (fn) {
- if (self.started) {
- $.error("Subscribing to stage which already started!");
- }
- self.events.push(fn);
- };
- self.unsubscribe = function (fn) {
- self.events.remove(fn);
- };
- self.executeSubscribedFn = function (fn) {
- var d = $.Deferred();
- self.outstanding.push(d);
- // display an error if our done() callback is not called
- $.md.util.wait(2500).done(function () {
- if (d.state() !== "resolved") {
- log.fatal(
- "Timeout reached for done callback in stage: " +
- self.name +
- ". Did you forget a done() call in a .subscribe() ?"
- );
- log.fatal("stage " + name + " failed running subscribed function: " + fn);
- }
- });
- var done = function () {
- d.resolve();
- };
- fn(done);
- };
- self.run = function () {
- self.started = true;
- $(self.events).each(function (i, fn) {
- self.executeSubscribedFn(fn);
- });
- // if no events are in our queue, we resolve immediately
- if (self.outstanding.length === 0) {
- self.resolve();
- }
- // we resolve when all our registered events have completed
- $.when
- .apply($, self.outstanding)
- .done(function () {
- self.resolve();
- })
- .fail(function () {
- self.resolve();
- });
- };
- self.done(function () {
- log.debug("stage " + self.name + " completed successfully.");
- });
- self.fail(function () {
- log.debug("stage " + self.name + " completed with errors!");
- });
- return self;
- };
- })(jQuery);
- (function ($) {
- "use strict";
- var log = $.md.getLogger();
- function init() {
- $.md.stages = [
- $.Stage("init"),
- // loads config, initial markdown and navigation
- $.Stage("load"),
- // will transform the markdown to html
- $.Stage("transform"),
- // HTML transformation finished
- $.Stage("ready"),
- // after we have a polished html skeleton
- $.Stage("skel_ready"),
- // will bootstrapify the skeleton
- $.Stage("bootstrap"),
- // before we run any gimmicks
- $.Stage("pregimmick"),
- // after we have bootstrapified the skeleton
- $.Stage("gimmick"),
- // postprocess
- $.Stage("postgimmick"),
- $.Stage("all_ready"),
- // used for integration tests, not intended to use in MDwiki itself
- $.Stage("final_tests"),
- ];
- $.md.stage = function (name) {
- var m = $.grep($.md.stages, function (e, i) {
- return e.name === name;
- });
- if (m.length === 0) {
- $.error("A stage by name " + name + " does not exist");
- } else {
- return m[0];
- }
- };
- }
- init();
- function resetStages() {
- var old_stages = $.md.stages;
- $.md.stages = [];
- $(old_stages).each(function (i, e) {
- $.md.stages.push($.Stage(e.name));
- });
- }
- var publicMethods = {};
- $.md.publicMethods = $.extend({}, $.md.publicMethods, publicMethods);
- function transformMarkdown(markdown) {
- var options = {
- gfm: true,
- tables: true,
- breaks: true,
- };
- if ($.md.config.lineBreaks === "original") options.breaks = false;
- else if ($.md.config.lineBreaks === "gfm") options.breaks = true;
- marked.setOptions(options);
- // get sample markdown
- var uglyHtml = marked(markdown);
- return uglyHtml;
- }
- function registerFetchMarkdown() {
- var md = "";
- $.md.stage("init").subscribe(function (done) {
- var ajaxReq = {
- url: $.md.mainHref,
- dataType: "text",
- };
- // Request the md page
- $.ajax(ajaxReq)
- .done(function (data) {
- md = data;
- done();
- })
- // Failed to find the md page we were looking for
- .fail(function () {
- // Warn that this page wasn't found
- var log = $.md.getLogger();
- log.warn("Could not get " + $.md.mainHref);
- // Attempt to gracefully recover by displaying a user defined 404 page
- ajaxReq.url = "404.md";
- $.ajax(ajaxReq)
- .done(function (data) {
- md = data;
- done();
- })
- // The user has not defined a 404.md.
- .fail(function (data) {
- log.fatal("Could not get a user defined 404.md");
- // Our last attempt to provide a good user expierence by proving a hard coded
- // 'page not found' text.
- md = "# Page Not Found";
- done();
- });
- });
- });
- // find baseUrl
- $.md.stage("transform").subscribe(function (done) {
- var len = $.md.mainHref.lastIndexOf("/");
- var baseUrl = $.md.mainHref.substring(0, len + 1);
- $.md.baseUrl = baseUrl;
- done();
- });
- $.md.stage("transform").subscribe(function (done) {
- var uglyHtml = transformMarkdown(md);
- $("#md-content").html(uglyHtml);
- md = "";
- var dfd = $.Deferred();
- loadExternalIncludes(dfd);
- dfd.always(function () {
- done();
- });
- });
- }
- // load [include](/foo/bar.md) external links
- function loadExternalIncludes(parent_dfd) {
- function findExternalIncludes() {
- return $("a").filter(function () {
- var href = $(this).attr("href");
- var text = $(this).toptext();
- var isMarkdown = $.md.util.hasMarkdownFileExtension(href);
- var isInclude = text === "include";
- var isPreview = text.startsWith("preview:");
- return (isInclude || isPreview) && isMarkdown;
- });
- }
- function selectPreviewElements($jqcol, num_elements) {
- function isTextNode(node) {
- return node.nodeType === 3;
- }
- var count = 0;
- var elements = [];
- $jqcol.each(function (i, e) {
- if (count < num_elements) {
- elements.push(e);
- if (!isTextNode(e)) count++;
- }
- });
- return $(elements);
- }
- var external_links = findExternalIncludes();
- // continue execution when all external resources are fully loaded
- var latch = $.md.util.countDownLatch(external_links.length);
- latch.always(function () {
- parent_dfd.resolve();
- });
- external_links.each(function (i, e) {
- var $el = $(e);
- var href = $el.attr("href");
- var text = $el.toptext();
- $.ajax({
- url: href,
- dataType: "text",
- })
- .done(function (data) {
- var $html = $(transformMarkdown(data));
- if (text.startsWith("preview:")) {
- // only insert the selected number of paragraphs; default 3
- var num_preview_elements = parseInt(text.substring(8), 10) || 3;
- var $preview = selectPreviewElements($html, num_preview_elements);
- $preview.last().append('<a href="' + href + '"> ...read more ➜</a>');
- $preview.insertBefore($el.parent("p").eq(0));
- $el.remove();
- } else {
- $html.insertAfter($el.parents("p"));
- $el.remove();
- }
- })
- .always(function () {
- latch.countDown();
- });
- });
- }
- function isSpecialLink(href) {
- if (!href) return false;
- if (href.lastIndexOf("data:") >= 0) return true;
- if (href.startsWith("mailto:")) return true;
- if (href.startsWith("file:")) return true;
- if (href.startsWith("ftp:")) return true;
- // TODO capture more special links: every non-http link with : like
- // torrent:// etc.
- }
- // modify internal links so we load them through our engine
- function processPageLinks(domElement, baseUrl) {
- var html = $(domElement);
- if (baseUrl === undefined) {
- baseUrl = "";
- }
- // HACK against marked: empty links will have empy href attribute
- // we remove the href attribute from the a tag
- html.find("a")
- .not("#md-menu a")
- .filter(function () {
- var $this = $(this);
- var attr = $this.attr("href");
- if (!attr || attr.length === 0) $this.removeAttr("href");
- });
- html.find("a, img").each(function (i, e) {
- var link = $(e);
- // link must be jquery collection
- var isImage = false;
- var hrefAttribute = "href";
- if (!link.attr(hrefAttribute)) {
- isImage = true;
- hrefAttribute = "src";
- }
- var href = link.attr(hrefAttribute);
- if (href && href.lastIndexOf("#!") >= 0) return;
- if (isSpecialLink(href)) return;
- if (!isImage && href.startsWith("#") && !href.startsWith("#!")) {
- // in-page link
- link.click(function (ev) {
- ev.preventDefault();
- $.md.scrollToInPageAnchor(href);
- });
- }
- if (!$.md.util.isRelativeUrl(href)) return;
- if (isImage && !$.md.util.isRelativePath(href)) return;
- if (!isImage && $.md.util.isGimmickLink(link)) return;
- function build_link(url) {
- if ($.md.util.hasMarkdownFileExtension(url)) return "#!" + url;
- else return url;
- }
- var newHref = baseUrl + href;
- if (isImage) link.attr(hrefAttribute, newHref);
- else if ($.md.util.isRelativePath(href)) link.attr(hrefAttribute, build_link(newHref));
- else link.attr(hrefAttribute, build_link(href));
- });
- }
- var navMD = "";
- $.md.NavigationDfd = $.Deferred();
- var ajaxReq = {
- url: "navigation.md",
- dataType: "text",
- };
- $.ajax(ajaxReq)
- .done(function (data) {
- navMD = data;
- $.md.NavigationDfd.resolve();
- })
- .fail(function () {
- $.md.NavigationDfd.reject();
- });
- function registerBuildNavigation() {
- $.md.stage("init").subscribe(function (done) {
- $.md.NavigationDfd.done(function () {
- done();
- }).fail(function () {
- done();
- });
- });
- $.md.stage("transform").subscribe(function (done) {
- if (navMD === "") {
- var log = $.md.getLogger();
- log.info("no navgiation.md found, not using a navbar");
- done();
- return;
- }
- var navHtml = marked(navMD);
- // TODO why are <script> tags from navHtml APPENDED to the jqcol?
- var $h = $("<div>" + navHtml + "</div>");
- // insert <scripts> from navigation.md into the DOM
- $h.each(function (i, e) {
- if (e.tagName === "SCRIPT") {
- $("script").first().before(e);
- }
- });
- // TODO .html() is evil!!!
- var $navContent = $h.eq(0);
- $navContent.find("p").each(function (i, e) {
- var $el = $(e);
- $el.replaceWith($el.html());
- });
- $("#md-menu").append($navContent.html());
- done();
- });
- $.md.stage("bootstrap").subscribe(function (done) {
- processPageLinks($("#md-menu"));
- done();
- });
- $.md.stage("postgimmick").subscribe(function (done) {
- var num_links = $("#md-menu a").length;
- var has_header = $("#md-menu .navbar-brand").eq(0).toptext().trim().length > 0;
- if (!has_header && num_links <= 1) $("#md-menu").hide();
- done();
- });
- }
- $.md.ConfigDfd = $.Deferred();
- $.ajax({ url: "config.json", dataType: "text" })
- .done(function (data) {
- try {
- var data_json = JSON.parse(data);
- $.md.config = $.extend($.md.config, data_json);
- log.info("Found a valid config.json file, using configuration");
- } catch (err) {
- log.error("config.json was not JSON parsable: " + err);
- }
- $.md.ConfigDfd.resolve();
- })
- .fail(function (err, textStatus) {
- log.error("unable to retrieve config.json: " + textStatus);
- $.md.ConfigDfd.reject();
- });
- function registerFetchConfig() {
- $.md.stage("init").subscribe(function (done) {
- // TODO 404 won't get cached, requesting it every reload is not good
- // maybe use cookies? or disable re-loading of the page
- //$.ajax('config.json').done(function(data){
- $.md.ConfigDfd.done(function () {
- done();
- }).fail(function () {
- var log = $.md.getLogger();
- log.info("No config.json found, using default settings");
- done();
- });
- });
- }
- function registerClearContent() {
- $.md.stage("init").subscribe(function (done) {
- $("#md-all").empty();
- var skel =
- '<div id="md-body"><div id="md-title"></div><div id="md-menu">' +
- '</div><div id="md-content"></div></div>';
- $("#md-all").prepend($(skel));
- done();
- });
- }
- function loadContent(href) {
- if (href.startsWith("/")) {
- // prevent cross-domain inclusions to prevent possible XSS
- href = "/./" + href;
- } else {
- href = "./" + href;
- }
- $.md.mainHref = href;
- registerFetchMarkdown();
- registerClearContent();
- // find out which link gimmicks we need
- $.md.stage("ready").subscribe(function (done) {
- $.md.initializeGimmicks();
- $.md.registerLinkGimmicks();
- done();
- });
- // wire up the load method of the modules
- $.each($.md.gimmicks, function (i, module) {
- if (module.load === undefined) {
- return;
- }
- $.md.stage("load").subscribe(function (done) {
- module.load();
- done();
- });
- });
- $.md.stage("ready").subscribe(function (done) {
- $.md("createBasicSkeleton");
- done();
- });
- $.md.stage("bootstrap").subscribe(function (done) {
- $.mdbootstrap("bootstrapify");
- processPageLinks($("#md-content"), $.md.baseUrl);
- done();
- });
- runStages();
- }
- function runStages() {
- // wire the stages up
- $.md.stage("init").done(function () {
- $.md.stage("load").run();
- });
- $.md.stage("load").done(function () {
- $.md.stage("transform").run();
- });
- $.md.stage("transform").done(function () {
- $.md.stage("ready").run();
- });
- $.md.stage("ready").done(function () {
- $.md.stage("skel_ready").run();
- });
- $.md.stage("skel_ready").done(function () {
- $.md.stage("bootstrap").run();
- });
- $.md.stage("bootstrap").done(function () {
- $.md.stage("pregimmick").run();
- });
- $.md.stage("pregimmick").done(function () {
- $.md.stage("gimmick").run();
- });
- $.md.stage("gimmick").done(function () {
- $.md.stage("postgimmick").run();
- });
- $.md.stage("postgimmick").done(function () {
- $.md.stage("all_ready").run();
- });
- $.md.stage("all_ready").done(function () {
- $("html").removeClass("md-hidden-load");
- // phantomjs hook when we are done
- if (typeof window.callPhantom === "function") {
- window.callPhantom({});
- }
- $.md.stage("final_tests").run();
- });
- $.md.stage("final_tests").done(function () {
- // reset the stages for next iteration
- resetStages();
- // required by dalekjs so we can wait the element to appear
- $("body").append('<span id="start-tests"></span>');
- $("#start-tests").hide();
- });
- // trigger the whole process by runing the init stage
- $.md.stage("init").run();
- return;
- }
- function extractHashData() {
- // first char is the # or #!
- var href;
- if (window.location.hash.startsWith("#!")) {
- href = window.location.hash.substring(2);
- } else {
- href = window.location.hash.substring(1);
- }
- href = decodeURIComponent(href);
- // extract possible in-page anchor
- var ex_pos = href.indexOf("#");
- if (ex_pos !== -1) {
- $.md.inPageAnchor = href.substring(ex_pos + 1);
- $.md.mainHref = href.substring(0, ex_pos);
- } else {
- $.md.mainHref = href;
- }
- }
- function appendDefaultFilenameToHash() {
- var newHashString = "";
- var currentHashString = window.location.hash || "";
- if (currentHashString === "" || currentHashString === "#" || currentHashString === "#!") {
- newHashString = "#!index.md";
- } else if (currentHashString.startsWith("#!") && currentHashString.endsWith("/")) {
- newHashString = currentHashString + "index.md";
- }
- if (newHashString) window.location.hash = newHashString;
- }
- $(document).ready(function () {
- // stage init stuff
- registerFetchConfig();
- registerBuildNavigation();
- extractHashData();
- appendDefaultFilenameToHash();
- $(window).bind("hashchange", function () {
- window.location.reload(false);
- });
- loadContent($.md.mainHref);
- });
- })(jQuery);
- (function ($) {
- var publicMethods = {
- isRelativeUrl: function (url) {
- if (url === undefined) {
- return false;
- }
- // if there is :// in it, its considered absolute
- // else its relative
- if (url.indexOf("://") === -1) {
- return true;
- } else {
- return false;
- }
- },
- isRelativePath: function (path) {
- if (path === undefined) return false;
- if (path.startsWith("/")) return false;
- return true;
- },
- isGimmickLink: function (domAnchor) {
- if (domAnchor.toptext().indexOf("gimmick:") !== -1) {
- return true;
- } else {
- return false;
- }
- },
- hasMarkdownFileExtension: function (str) {
- var markdownExtensions = [".md", ".markdown", ".mdown"];
- var result = false;
- var value = str.toLowerCase().split("#")[0];
- $(markdownExtensions).each(function (i, ext) {
- if (value.toLowerCase().endsWith(ext)) {
- result = true;
- }
- });
- return result;
- },
- wait: function (time) {
- return $.Deferred(function (dfd) {
- setTimeout(dfd.resolve, time);
- });
- },
- };
- $.md.util = $.extend({}, $.md.util, publicMethods);
- if (typeof String.prototype.startsWith !== "function") {
- String.prototype.startsWith = function (str) {
- return this.slice(0, str.length) === str;
- };
- }
- if (typeof String.prototype.endsWith !== "function") {
- String.prototype.endsWith = function (str) {
- return this.slice(this.length - str.length, this.length) === str;
- };
- }
- $.fn.extend({
- toptext: function () {
- return this.clone().children().remove().end().text();
- },
- });
- // adds a :icontains selector to jQuery that is case insensitive
- $.expr[":"].icontains = $.expr.createPseudo(function (arg) {
- return function (elem) {
- return $(elem).toptext().toUpperCase().indexOf(arg.toUpperCase()) >= 0;
- };
- });
- $.md.util.getInpageAnchorText = function (text) {
- var subhash = text.replace(/ /g, "_");
- // TODO remove more unwanted characters like ?/,- etc.
- return subhash;
- };
- $.md.util.getInpageAnchorHref = function (text, href) {
- href = href || $.md.mainHref;
- var subhash = $.md.util.getInpageAnchorText(text);
- return "#!" + href + "#" + subhash;
- };
- $.md.util.repeatUntil = function (interval, predicate, maxRepeats) {
- maxRepeats = maxRepeats || 10;
- var dfd = $.Deferred();
- function recursive_repeat(interval, predicate, maxRepeats) {
- if (maxRepeats === 0) {
- dfd.reject();
- return;
- }
- if (predicate()) {
- dfd.resolve();
- return;
- } else {
- $.md.util.wait(interval).always(function () {
- recursive_repeat(interval, predicate, maxRepeats - 1);
- });
- }
- }
- recursive_repeat(interval, predicate, maxRepeats);
- return dfd;
- };
- // a count-down latch as in Java7.
- $.md.util.countDownLatch = function (capacity, min) {
- min = min || 0;
- var dfd = $.Deferred();
- if (capacity <= min) dfd.resolve();
- dfd.capacity = capacity;
- dfd.countDown = function () {
- dfd.capacity--;
- if (dfd.capacity <= min) dfd.resolve();
- };
- return dfd;
- };
- })(jQuery);
- (function ($) {
- "use strict";
- // PUBLIC API
- $.md.registerGimmick = function (module) {
- $.md.gimmicks.push(module);
- return;
- };
- // registers a script for a gimmick, that is later dynamically loaded
- // by the core.
- // src may be an URL or direct javascript sourcecode. When options.callback
- // is provided, the done() function is passed to the function and needs to
- // be called.
- $.md.registerScript = function (module, src, options) {
- var scriptinfo = new ScriptInfo({
- module: module,
- src: src,
- options: options,
- });
- registeredScripts.push(scriptinfo);
- };
- // same as registerScript but for css. Note that we do not provide a
- // callback when the load finishes
- $.md.registerCss = function (module, url, options) {
- var license = options.license,
- stage = options.stage || "skel_ready",
- callback = options.callback;
- checkLicense(license, module);
- var tag = '<link rel="stylesheet" href="' + url + '" type="text/css"></link>';
- $.md.stage(stage).subscribe(function (done) {
- $("head").append(tag);
- if (callback !== undefined) {
- callback(done);
- } else {
- done();
- }
- });
- };
- // turns hostname/path links into http://hostname/path links
- // we need to do this because if accessed by file:///, we need a different
- // transport scheme for external resources (like http://)
- $.md.prepareLink = function (link, options) {
- options = options || {};
- var ownProtocol = window.location.protocol;
- if (options.forceSSL) return "https://" + link;
- if (options.forceHTTP) return "http://" + link;
- if (ownProtocol === "file:") {
- return "http://" + link;
- }
- // default: use the same as origin resource
- return "//" + link;
- };
- // associate a link trigger for a gimmick. i.e. [gimmick:foo]() then
- // foo is the trigger and will invoke the corresponding gimmick
- $.md.linkGimmick = function (module, trigger, callback, stage) {
- if (stage === undefined) {
- stage = "gimmick";
- }
- var linktrigger = new LinkTrigger({
- trigger: trigger,
- module: module,
- stage: stage,
- callback: callback,
- });
- linkTriggers.push(linktrigger);
- };
- $.md.triggerIsActive = function (trigger) {
- if (activeLinkTriggers.indexOf(trigger) === -1) {
- return false;
- } else {
- return true;
- }
- };
- var initialized = false;
- // TODO combine main.js and modules.js closure
- $.md.initializeGimmicks = function () {
- findActiveLinkTrigger();
- runGimmicksOnce();
- loadRequiredScripts();
- };
- // END PUBLIC API
- var log = $.md.getLogger();
- // triggers that we actually found on the page
- // array of string
- var activeLinkTriggers = [];
- // array of ScriptInfo
- var registeredScripts = [];
- function ScriptInfo(initial) {
- this.module = undefined;
- this.options = {};
- // can ba an URL or javascript sourcecode
- this.src = "";
- $.extend(this, initial);
- }
- // array of linkTriggers
- var linkTriggers = [];
- function LinkTrigger(initial) {
- this.trigger = undefined;
- this.module = undefined;
- this.callback = undefined;
- $.extend(this, initial);
- }
- // jQuery does some magic when inserting inline scripts, so better
- // use vanilla JS. See:
- // http://stackoverflow.com/questions/610995/jquery-cant-append-script-element
- function insertInlineScript(src) {
- // scripts always need to go directly into the DOM
- var script = document.createElement("script");
- script.type = "text/javascript";
- script.text = src;
- document.body.appendChild(script);
- }
- // since we are GPL, we have to be cautious what other scripts we load
- // as delivering to the browser is considered delivering a derived work
- var licenses = [
- "MIT",
- "BSD",
- "GPL",
- "GPL2",
- "GPL3",
- "LGPL",
- "LGPL2",
- "APACHE2",
- "PUBLICDOMAIN",
- "EXCEPTION",
- "OTHER",
- ];
- function checkLicense(license, module) {
- if ($.inArray(license, licenses) === -1) {
- var availLicenses = JSON.stringify(licenses);
- log.warn("license " + license + " is not known.");
- log.warn("Known licenses:" + availLicenses);
- } else if (license === "OTHER") {
- log.warn(
- "WARNING: Module " +
- module.name +
- " uses a script" +
- " with unknown license. This may be a GPL license violation if" +
- " this website is publically available!"
- );
- }
- }
- // will actually schedule the script load into the DOM.
- function loadScript(scriptinfo) {
- var module = scriptinfo.module,
- src = scriptinfo.src,
- options = scriptinfo.options;
- var license = options.license || "OTHER",
- loadstage = options.loadstage || "skel_ready",
- finishstage = options.finishstage || "pregimmick",
- callback = options.callback;
- var loadDone = $.Deferred();
- checkLicense(license, module);
- // start script loading
- log.debug("subscribing " + module.name + " to start: " + loadstage + " end in: " + finishstage);
- $.md.stage(loadstage).subscribe(function (done) {
- if (src.startsWith("//") || src.startsWith("http")) {
- $.getScript(src, function () {
- if (callback !== undefined) {
- callback(done);
- } else {
- log.debug("module" + module.name + " script load done: " + src);
- done();
- }
- loadDone.resolve();
- });
- } else {
- // inline script that we directly insert
- insertInlineScript(src);
- log.debug("module" + module.name + " script inject done");
- loadDone.resolve();
- done();
- }
- });
- // if loading is not yet finished in stage finishstage, wait
- // for the loading to complete
- $.md.stage(finishstage).subscribe(function (done) {
- loadDone.done(function () {
- done();
- });
- });
- }
- // finds out that kind of trigger words are acutally used on a given page
- // this is most likely a very small subset of all available gimmicks
- function findActiveLinkTrigger() {
- var $gimmicks = $("a:icontains(gimmick:)");
- $gimmicks.each(function (i, e) {
- var parts = getGimmickLinkParts($(e));
- if (activeLinkTriggers.indexOf(parts.trigger) === -1) {
- activeLinkTriggers.push(parts.trigger);
- }
- });
- log.debug("Scanning for required gimmick links: " + JSON.stringify(activeLinkTriggers));
- }
- function loadRequiredScripts() {
- // find each module responsible for the link trigger
- $.each(activeLinkTriggers, function (i, trigger) {
- var module = findModuleByTrigger(trigger);
- if (module === undefined) {
- log.error('Gimmick link: "' + trigger + '" found but no suitable gimmick loaded');
- return;
- }
- var scriptinfo = registeredScripts.filter(function (info) {
- return info.module.name === module.name;
- })[0];
- // register to load the script
- if (scriptinfo !== undefined) {
- loadScript(scriptinfo);
- }
- });
- }
- function findModuleByTrigger(trigger) {
- var ret;
- $.each(linkTriggers, function (i, e) {
- if (e.trigger === trigger) {
- ret = e.module;
- }
- });
- return ret;
- }
- function getGimmickLinkParts($link) {
- var link_text = $.trim($link.toptext());
- // returns linkTrigger, options, linkText
- if (link_text.match(/gimmick:/i) === null) {
- return null;
- }
- var href = $.trim($link.attr("href"));
- var r = new RegExp(/gimmick:\s*([^(\s]*)\s*(\(\s*{?(.*)\s*}?\s*\))*/i);
- var matches = r.exec(link_text);
- if (matches === null || matches[1] === undefined) {
- $.error("Error matching a gimmick: " + link_text);
- return null;
- }
- var trigger = matches[1].toLowerCase();
- var args = null;
- // getting the parameters
- if (matches[2] !== undefined) {
- // remove whitespaces
- var params = $.trim(matches[3].toString());
- // remove the closing } if present
- if (params.charAt(params.length - 1) === "}") {
- params = params.substring(0, params.length - 1);
- }
- // add surrounding braces and paranthese
- params = "({" + params + "})";
- // replace any single quotes by double quotes
- params = params.replace(/'/g, '"');
- // finally, try if the json object is valid
- try {
- /*jshint -W061 */
- args = eval(params);
- } catch (err) {
- log.error("error parsing argument of gimmick: " + link_text + "giving error: " + err);
- }
- }
- return { trigger: trigger, options: args, href: href };
- }
- function runGimmicksOnce() {
- // runs the once: callback for each gimmick within the init stage
- $.each($.md.gimmicks, function (i, module) {
- if (module.once === undefined) {
- return;
- }
- module.once();
- });
- }
- // activate all gimmicks on a page, that are contain the text gimmick:
- // TODO make private / merge closures
- $.md.registerLinkGimmicks = function () {
- var $gimmick_links = $("a:icontains(gimmick:)");
- $gimmick_links.each(function (i, e) {
- var $link = $(e);
- var gimmick_arguments = getGimmickLinkParts($link);
- $.each(linkTriggers, function (i, linktrigger) {
- if (gimmick_arguments.trigger === linktrigger.trigger) {
- subscribeLinkTrigger($link, gimmick_arguments, linktrigger);
- }
- });
- });
- };
- function subscribeLinkTrigger($link, args, linktrigger) {
- log.debug("Subscribing gimmick " + linktrigger.module.name + " to stage: " + linktrigger.stage);
- $.md.stage(linktrigger.stage).subscribe(function (done) {
- args.options = args.options || {};
- // it is possible that broken modules or any other transformation removed the $link
- // from the dom in the meantime
- if (!jQuery.contains(document.documentElement, $link[0])) {
- log.error("LINK IS NOT IN THE DOM ANYMORE: ");
- console.log($link);
- }
- log.debug("Running gimmick " + linktrigger.module.name);
- linktrigger.callback($link, args.options, args.href, done);
- // if the gimmick didn't call done, we trigger it here
- done();
- });
- }
- })(jQuery);
- (function ($) {
- var publicMethods = {
- createBasicSkeleton: function () {
- setPageTitle();
- wrapParagraphText();
- linkImagesToSelf();
- groupImages();
- removeBreaks();
- addInpageAnchors();
- $.md.stage("all_ready").subscribe(function (done) {
- if ($.md.inPageAnchor !== "") {
- $.md.util.wait(500).then(function () {
- $.md.scrollToInPageAnchor($.md.inPageAnchor);
- });
- }
- done();
- });
- return;
- },
- };
- $.md.publicMethods = $.extend({}, $.md.publicMethods, publicMethods);
- // set the page title to the browser document title, optionally picking
- // the first h1 element as title if no title is given
- function setPageTitle() {
- var $pageTitle;
- if ($.md.config.title) $("title").text($.md.config.title);
- $pageTitle = $("#md-content h1").eq(0);
- if ($.trim($pageTitle.toptext()).length > 0) {
- $("#md-title").prepend($pageTitle);
- var title = $pageTitle.toptext();
- // document.title = title;
- } else {
- $("#md-title").remove();
- }
- }
- function wrapParagraphText() {
- // TODO is this true for marked.js?
- // markdown gives us sometime paragraph that contain child tags (like img),
- // but the containing text is not wrapped. Make sure to wrap the text in the
- // paragraph into a <div>
- // this also moves ANY child tags to the front of the paragraph!
- $("#md-content p").each(function () {
- var $p = $(this);
- // nothing to do for paragraphs without text
- if ($.trim($p.text()).length === 0) {
- // make sure no whitespace are in the p and then exit
- //$p.text ('');
- return;
- }
- // children elements of the p
- var children = $p.contents().filter(function () {
- var $child = $(this);
- // we extract images and hyperlinks with images out of the paragraph
- if (this.tagName === "A" && $child.find("img").length > 0) {
- return true;
- }
- if (this.tagName === "IMG") {
- return true;
- }
- // else
- return false;
- });
- var floatClass = getFloatClass($p);
- $p.wrapInner('<div class="md-text" />');
- // if there are no children, we are done
- if (children.length === 0) {
- return;
- }
- // move the children out of the wrapped div into the original p
- children.prependTo($p);
- // at this point, we now have a paragraph that holds text AND images
- // we mark that paragraph to be a floating environment
- // TODO determine floatenv left/right
- $p.addClass("md-floatenv").addClass(floatClass);
- });
- }
- function removeBreaks() {
- // since we use non-markdown-standard line wrapping, we get lots of
- // <br> elements we don't want.
- // remove a leading <br> from floatclasses, that happen to
- // get insertet after an image
- $(".md-floatenv")
- .find(".md-text")
- .each(function () {
- var $first = $(this).find("*").eq(0);
- if ($first.is("br")) {
- $first.remove();
- }
- });
- // remove any breaks from image groups
- $(".md-image-group").find("br").remove();
- }
- function getFloatClass(par) {
- var $p = $(par);
- var floatClass = "";
- // reduce content of the paragraph to images
- var nonTextContents = $p.contents().filter(function () {
- if (this.tagName === "IMG" || this.tagName === "IFRAME") {
- return true;
- } else if (this.tagName === "A") {
- return $(this).find("img").length > 0;
- } else {
- return $.trim($(this).text()).length > 0;
- }
- });
- // check the first element - if its an image or a link with image, we go left
- var elem = nonTextContents[0];
- if (elem !== undefined && elem !== null) {
- if (elem.tagName === "IMG" || elem.tagName === "IFRAME") {
- floatClass = "md-float-left";
- } else if (elem.tagName === "A" && $(elem).find("img").length > 0) {
- floatClass = "md-float-left";
- } else {
- floatClass = "md-float-right";
- }
- }
- return floatClass;
- }
- // images are put in the same image group as long as there is
- // not separating paragraph between them
- function groupImages() {
- var par = $("p img").parents("p");
- // add an .md-image-group class to the p
- par.addClass("md-image-group");
- }
- // takes a standard <img> tag and adds a hyperlink to the image source
- // needed since we scale down images via css and want them to be accessible
- // in original format
- function linkImagesToSelf() {
- function selectNonLinkedImages() {
- // only select images that do not have a non-empty parent link
- $images = $("img").filter(function (index) {
- var $parent_link = $(this).parents("a").eq(0);
- if ($parent_link.length === 0) return true;
- var attr = $parent_link.attr("href");
- return attr && attr.length === 0;
- });
- return $images;
- }
- var $images = selectNonLinkedImages();
- return $images.each(function () {
- var $this = $(this);
- var img_src = $this.attr("src");
- var img_title = $this.attr("title");
- if (img_title === undefined) {
- img_title = "";
- }
- // wrap the <img> tag in an anchor and copy the title of the image
- $this.wrap('<a class="md-image-selfref" href="' + img_src + '" title="' + img_title + '"/> ');
- });
- }
- function addInpageAnchors() {
- // adds a pilcrow (paragraph) character to heading with a link for the
- // inpage anchor
- function addPilcrow($heading, href) {
- var c = $.md.config.anchorCharacter;
- var $pilcrow = $('<span class="anchor-highlight"><a>' + c + "</a></span>");
- $pilcrow.find("a").attr("href", href);
- $pilcrow.hide();
- var mouse_entered = false;
- $heading.mouseenter(function () {
- mouse_entered = true;
- $.md.util.wait(300).then(function () {
- if (!mouse_entered) return;
- $pilcrow.fadeIn(200);
- });
- });
- $heading.mouseleave(function () {
- mouse_entered = false;
- $pilcrow.fadeOut(200);
- });
- $pilcrow.appendTo($heading);
- }
- // adds a link to the navigation at the top of the page
- function addJumpLinkToTOC($heading) {
- if ($.md.config.useSideMenu === false) return;
- if ($heading.prop("tagName") !== "H2") return;
- var c = $.md.config.tocAnchor;
- if (c === "") return;
- var $jumpLink = $('<a class="visible-xs visible-sm jumplink" href="#md-page-menu">' + c + "</a>");
- $jumpLink.click(function (ev) {
- ev.preventDefault();
- $("body").scrollTop($("#md-page-menu").position().top);
- });
- if ($heading.parents("#md-menu").length === 0) {
- $jumpLink.insertAfter($heading);
- }
- }
- // adds a page inline anchor to each h1,h2,h3,h4,h5,h6 element
- // which can be accessed by the headings text
- $("h1,h2,h3,h4,h5,h6")
- .not("#md-title h1")
- .each(function () {
- var $heading = $(this);
- $heading.addClass("md-inpage-anchor");
- var text = $heading.clone().children(".anchor-highlight").remove().end().text();
- var href = $.md.util.getInpageAnchorHref(text);
- addPilcrow($heading, href);
- //add jumplink to table of contents
- addJumpLinkToTOC($heading);
- });
- }
- $.md.scrollToInPageAnchor = function (anchortext) {
- if (anchortext.startsWith("#")) anchortext = anchortext.substring(1, anchortext.length);
- // we match case insensitive
- var doBreak = false;
- $(".md-inpage-anchor").each(function () {
- if (doBreak) {
- return;
- }
- var $this = $(this);
- // don't use the text of any subnode
- var text = $this.toptext();
- var match = $.md.util.getInpageAnchorText(text);
- if (anchortext === match) {
- this.scrollIntoView(true);
- var navbar_offset = $(".navbar-collapse").height() + 5;
- window.scrollBy(0, -navbar_offset + 5);
- doBreak = true;
- }
- });
- };
- })(jQuery);
- (function ($) {
- "use strict";
- // call the gimmick
- $.mdbootstrap = function (method) {
- if ($.mdbootstrap.publicMethods[method]) {
- return $.mdbootstrap.publicMethods[method].apply(this, Array.prototype.slice.call(arguments, 1));
- } else {
- $.error("Method " + method + " does not exist on jquery.mdbootstrap");
- }
- };
- // simple wrapper around $().bind
- $.mdbootstrap.events = [];
- $.mdbootstrap.bind = function (ev, func) {
- $(document).bind(ev, func);
- $.mdbootstrap.events.push(ev);
- };
- $.mdbootstrap.trigger = function (ev) {
- $(document).trigger(ev);
- };
- var navStyle = "";
- // PUBLIC API functions that are exposed
- var publicMethods = {
- bootstrapify: function () {
- createPageSkeleton();
- buildMenu();
- changeHeading();
- replaceImageParagraphs();
- $("table").addClass("table").addClass("table-bordered");
- //pullRightBumper ();
- // remove the margin for headings h1 and h2 that are the first
- // on page
- //if (navStyle == "sub" || (navStyle == "top" && $('#md-title').text ().trim ().length === 0))
- // $(".md-first-heading").css ("margin-top", "0");
- // external content should run after gimmicks were run
- $.md.stage("pregimmick").subscribe(function (done) {
- if ($.md.config.useSideMenu !== false) {
- createPageContentMenu();
- }
- addAdditionalFooterText();
- done();
- });
- $.md.stage("postgimmick").subscribe(function (done) {
- adjustExternalContent();
- highlightActiveLink();
- done();
- });
- },
- };
- // register the public API functions
- $.mdbootstrap.publicMethods = $.extend({}, $.mdbootstrap.publicMethods, publicMethods);
- // PRIVATE FUNCTIONS:
- function buildTopNav() {
- // replace with the navbar skeleton
- if ($("#md-menu").length <= 0) {
- return;
- }
- navStyle = "top";
- var $menuContent = $("#md-menu").children();
- // $('#md-menu').addClass ('navbar navbar-default navbar-fixed-top');
- // var menusrc = '';
- // menusrc += '<div id="md-menu-inner" class="container">';
- // menusrc += '<ul id="md-menu-ul" class="nav navbar-nav">';
- // menusrc += '</ul></div>';
- var navbar = "";
- navbar += '<div id="md-main-navbar" class="navbar navbar-default navbar-fixed-top" role="navigation">';
- navbar += '<div class="navbar-header">';
- navbar +=
- '<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse">';
- navbar += '<span class="sr-only">Toggle navigation</span>';
- navbar += '<span class="icon-bar"></span>';
- navbar += '<span class="icon-bar"></span>';
- navbar += '<span class="icon-bar"></span>';
- navbar += "</button>";
- navbar += '<a class="navbar-brand" href="#"></a>';
- navbar += "</div>";
- navbar += '<div class="collapse navbar-collapse navbar-ex1-collapse">';
- navbar += '<ul class="nav navbar-nav" />';
- navbar += '<ul class="nav navbar-nav navbar-right" />';
- navbar += "</div>";
- navbar += "</div>";
- var $navbar = $(navbar);
- $navbar.appendTo("#md-menu");
- // .eq(0) becase we dont want navbar-right to be appended to
- $("#md-menu ul.nav").eq(0).append($menuContent);
- // the menu should be the first element in the body
- $("#md-menu").prependTo("#md-all");
- var brand_text = $("#md-menu h1").toptext();
- $("#md-menu h1").remove();
- $("a.navbar-brand").text(brand_text);
- // initial offset
- $("#md-body").css("margin-top", "70px");
- $.md.stage("pregimmick").subscribe(function (done) {
- check_offset_to_navbar();
- done();
- });
- }
- // the navbar has different height depending on theme, number of navbar entries,
- // and window/device width. Therefore recalculate on start and upon window resize
- function set_offset_to_navbar() {
- var height = $("#md-main-navbar").height() + 10;
- $("#md-body").css("margin-top", height + "px");
- }
- function check_offset_to_navbar() {
- // HACK this is VERY UGLY. When an external theme is used, we don't know when the
- // css style will be finished loading - and we can only correctly calculate
- // the height AFTER it has completely loaded.
- var navbar_height = 0;
- var dfd1 = $.md.util.repeatUntil(
- 40,
- function () {
- navbar_height = $("#md-main-navbar").height();
- return navbar_height > 35 && navbar_height < 481;
- },
- 25
- );
- dfd1.done(function () {
- navbar_height = $("#md-main-navbar").height();
- set_offset_to_navbar();
- // now bootstrap changes this maybe after a while, again watch for changes
- var dfd2 = $.md.util.repeatUntil(
- 20,
- function () {
- return navbar_height !== $("#md-main-navbar").height();
- },
- 25
- );
- dfd2.done(function () {
- // it changed, so we need to change it again
- set_offset_to_navbar();
- });
- // and finally, for real slow computers, make sure it is changed if changin very late
- $.md.util.wait(2000).done(function () {
- set_offset_to_navbar();
- });
- });
- }
- function buildSubNav() {
- // replace with the navbar skeleton
- /* BROKEN CODE
- if ($('#md-menu').length <= 0) {
- return;
- }
- navStyle = 'sub';
- var $menuContent = $('#md-menu').html ();
- var menusrc = '';
- menusrc += '<div id="md-menu-inner" class="subnav">';
- menusrc += '<ul id="md-menu-ul" class="nav nav-pills">';
- menusrc += $menuContent;
- menusrc += '</ul></div>';
- $('#md-menu').empty();
- $('#md-menu').wrapInner($(menusrc));
- $('#md-menu').addClass ('col-md-12');
- $('#md-menu-container').insertAfter ($('#md-title-container'));
- */
- }
- function buildMenu() {
- if ($("#md-menu a").length === 0) {
- return;
- }
- var h = $("#md-menu");
- // make toplevel <a> a dropdown
- h.find('> a[href=""]')
- .attr("data-toggle", "dropdown")
- .addClass("dropdown-toggle")
- .attr("href", "")
- .append('<b class="caret"/>');
- h.find("ul").addClass("dropdown-menu");
- h.find("ul li").addClass("dropdown");
- // replace hr with dividers
- $("#md-menu hr").each(function (i, e) {
- var hr = $(e);
- var prev = hr.prev();
- var next = hr.next();
- if (prev.is("ul") && prev.length >= 0) {
- prev.append($('<li class="divider"/>'));
- hr.remove();
- if (next.is("ul")) {
- next.find("li").appendTo(prev);
- next.remove();
- }
- // next ul should now be empty
- }
- return;
- });
- // remove empty uls
- $("#md-menu ul").each(function (i, e) {
- var ul = $(e);
- if (ul.find("li").length === 0) {
- ul.remove();
- }
- });
- $("#md-menu hr").replaceWith($('<li class="divider-vertical"/>'));
- // wrap the toplevel links in <li>
- $("#md-menu > a").wrap("<li />");
- $("#md-menu ul").each(function (i, e) {
- var ul = $(e);
- ul.appendTo(ul.prev());
- ul.parent("li").addClass("dropdown");
- });
- // submenu headers
- $("#md-menu li.dropdown")
- .find("h1, h2, h3")
- .each(function (i, e) {
- var $e = $(e);
- var text = $e.toptext();
- var header = $('<li class="dropdown-header" />');
- header.text(text);
- $e.replaceWith(header);
- });
- // call the user specifed menu function
- buildTopNav();
- }
- function isVisibleInViewport(e) {
- var el = $(e);
- var top = $(window).scrollTop();
- var bottom = top + $(window).height();
- var eltop = el.offset().top;
- var elbottom = eltop + el.height();
- return elbottom <= bottom && eltop >= top;
- }
- function createPageContentMenu() {
- // assemble the menu
- var $headings = $("#md-content").find("h2").clone();
- // we dont want the text of any child nodes
- $headings.children().remove();
- if ($headings.length <= 1) {
- return;
- }
- $("#md-content").removeClass("col-md-12");
- $("#md-content").addClass("col-md-9");
- $("#md-content-row").prepend('<div class="col-md-3" id="md-left-column"/>');
- var recalc_width = function () {
- // if the page menu is affixed, it is not a child of the
- // <md-left-column> anymore and therefore does not inherit
- // its width. On every resize, change the class accordingly
- var width_left_column = $("#md-left-column").css("width");
- $("#md-page-menu").css("width", width_left_column);
- };
- $(window).scroll(function () {
- recalc_width($("#md-page-menu"));
- var $first;
- $("*.md-inpage-anchor").each(function (i, e) {
- if ($first === undefined) {
- var h = $(e);
- if (isVisibleInViewport(h)) {
- $first = h;
- }
- }
- });
- // highlight in the right menu
- $("#md-page-menu a").each(function (i, e) {
- var $a = $(e);
- if ($first && $a.toptext() === $first.toptext()) {
- $("#md-page-menu a.active").removeClass("active");
- //$a.parent('a').addClass('active');
- $a.addClass("active");
- }
- });
- });
- var affixDiv = $('<div id="md-page-menu" />');
- //var top_spacing = $('#md-menu').height() + 15;
- var top_spacing = 70;
- affixDiv.affix({
- //offset: affix.position() - 50,
- offset: 130,
- });
- affixDiv.css("top", top_spacing);
- //affix.css('top','-250px');
- var $pannel = $('<div class="panel panel-default"><ul class="list-group"/></div>');
- var $ul = $pannel.find("ul");
- affixDiv.append($pannel);
- $headings.each(function (i, e) {
- var $heading = $(e);
- var $li = $('<li class="list-group-item" />');
- var $a = $("<a />");
- $a.attr("href", $.md.util.getInpageAnchorHref($heading.toptext()));
- $a.click(function (ev) {
- ev.preventDefault();
- var $this = $(this);
- var anchortext = $.md.util.getInpageAnchorText($this.toptext());
- $.md.scrollToInPageAnchor(anchortext);
- });
- $a.text($heading.toptext());
- $li.append($a);
- $ul.append($li);
- });
- $(window).resize(function () {
- recalc_width($("#md-page-menu"));
- check_offset_to_navbar();
- });
- $.md.stage("postgimmick").subscribe(function (done) {
- // recalc_width();
- done();
- });
- //menu.css('width','100%');
- $("#md-left-column").append(affixDiv);
- }
- function createPageSkeleton() {
- $("#md-title").wrap('<div class="container" id="md-title-container"/>');
- $("#md-title").wrap('<div class="row" id="md-title-row"/>');
- $("#md-menu").wrap('<div class="container" id="md-menu-container"/>');
- $("#md-menu").wrap('<div class="row" id="md-menu-row"/>');
- $("#md-content").wrap('<div class="container" id="md-content-container"/>');
- $("#md-content").wrap('<div class="row" id="md-content-row"/>');
- $("#md-body").wrap('<div class="container" id="md-body-container"/>');
- $("#md-body").wrap('<div class="row" id="md-body-row"/>');
- $("#md-title").addClass("col-md-12");
- $("#md-content").addClass("col-md-12");
- }
- function pullRightBumper() {
- /* $("span.bumper").each (function () {
- $this = $(this);
- $this.prev().addClass ("pull-right");
- });
- $('span.bumper').addClass ('pull-right');
- */
- }
- function changeHeading() {
- // HEADING
- var jumbo = $('<div class="page-header" />');
- $("#md-title").wrapInner(jumbo);
- }
- function highlightActiveLink() {
- // when no menu is used, return
- if ($("#md-menu").find("li").length === 0) {
- return;
- }
- var filename = window.location.hash;
- if (filename.length === 0) {
- filename = "#!index.md";
- }
- var selector = 'li:has(a[href="' + filename + '"])';
- $("#md-menu").find(selector).addClass("active");
- }
- // replace all <p> around images with a <div class="thumbnail" >
- function replaceImageParagraphs() {
- // only select those paragraphs that have images in them
- var $pars = $("p img").parents("p");
- $pars.each(function () {
- var $p = $(this);
- var $images = $(this)
- .find("img")
- .filter(function () {
- // only select those images that have no parent anchor
- return $(this).parents("a").length === 0;
- })
- // add those anchors including images
- .add($(this).find("img"))
- .addClass("img-responsive")
- .addClass("img-thumbnail");
- // create a new url group at the fron of the paragraph
- //$p.prepend($('<ul class="thumbnails" />'));
- // move the images to the newly created ul
- //$p.find('ul').eq(0).append($images);
- // wrap each image with a <li> that limits their space
- // the number of images in a paragraphs determines thei width / span
- // if the image is a link, wrap around the link to avoid
- function wrapImage($imgages, wrapElement) {
- return $images.each(function (i, img) {
- var $img = $(img);
- var $parent_img = $img.parent("a");
- if ($parent_img.length > 0) $parent_img.wrap(wrapElement);
- else $img.wrap(wrapElement);
- });
- }
- if ($p.hasClass("md-floatenv")) {
- if ($images.length === 1) {
- wrapImage($images, '<div class="col-sm-8" />');
- } else if ($images.length === 2) {
- wrapImage($images, '<div class="col-sm-4" />');
- } else {
- wrapImage($images, '<div class="col-sm-2" />');
- }
- } else {
- // non-float => images are on their own single paragraph, make em larger
- // but remember, our image resizing will make them only as large as they are
- // but do no upscaling
- // TODO replace by calculation
- if ($images.length === 1) {
- wrapImage($images, '<div class="col-sm-12" />');
- } else if ($images.length === 2) {
- wrapImage($images, '<div class="col-sm-6" />');
- } else if ($images.length === 3) {
- wrapImage($images, '<div class="col-sm-4" />');
- } else if ($images.length === 4) {
- wrapImage($images, '<div class="col-sm-3" />');
- } else {
- wrapImage($images, '<div class="col-sm-2" />');
- }
- }
- $p.addClass("row");
- // finally, every img gets its own wrapping thumbnail div
- //$images.wrap('<div class="thumbnail" />');
- });
- // apply float to the ul thumbnails
- //$('.md-floatenv.md-float-left ul').addClass ('pull-left');
- //$('.md-floatenv.md-float-right ul').addClass ('pull-right');
- }
- function adjustExternalContent() {
- // external content are usually iframes or divs that are integrated
- // by gimmicks
- // example: youtube iframes, google maps div canvas
- // all external content are in the md-external class
- $("iframe.md-external").not(".md-external-nowidth").attr("width", "450").css("width", "450px");
- $("iframe.md-external").not(".md-external-noheight").attr("height", "280").css("height", "280px");
- // make it appear like an image thumbnal
- //$('.md-external').addClass('img-thumbnail');
- //.wrap($("<ul class='thumbnails' />")).wrap($("<li class='col-md-6' />"));
- $("div.md-external").not(".md-external-noheight").css("height", "280px");
- $("div.md-external").not(".md-external-nowidth").css("width", "450px");
- // // make it appear like an image thumbnal
- // $("div.md-external").addClass("thumbnail").wrap($("<ul class='thumbnails' />")).wrap($("<li class='col-md-10' />"));
- // $("div.md-external-large").css('width', "700px")
- }
- // note: the footer is part of the GPLv3 legal information
- // and may not be removed or hidden to comply with licensing conditions.
- function addFooter() {
- var navbar = "";
- navbar += '<hr><div class="scontainer">';
- navbar += '<div class="pull-right md-copyright-footer"> ';
- navbar += '<span id="md-footer-additional"></span>';
- navbar += 'Website generated with <a href="http://www.mdwiki.info">MDwiki</a> ';
- navbar += "© Timo Dörr and contributors. ";
- navbar += "</div>";
- navbar += "</div>";
- var $navbar = $(navbar);
- $navbar.css("position", "relative");
- $navbar.css("margin-top", "1em");
- $("#md-all").append($navbar);
- }
- function addAdditionalFooterText() {
- var text = $.md.config.additionalFooterText;
- if (text) {
- $(".md-copyright-footer #md-footer-additional").html(text);
- }
- }
- })(jQuery);
- (function ($) {
- $.gimmicks = $.fn.gimmicks = function (method) {
- if (method === undefined) {
- return;
- }
- // call the gimmick
- if ($.fn.gimmicks.methods[method]) {
- return $.fn.gimmicks.methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
- } else {
- $.error("Gimmick " + method + " does not exist on jQuery.gimmicks");
- }
- };
- // TODO underscores _ in Markdown links are not allowed! bug in our MD imlemenation
- })(jQuery);
- (function ($) {
- //'use strict';
- var alertsGimmick = {
- name: "alerts",
- // TODO
- //version: $.md.version,
- load: function () {
- $.md.stage("bootstrap").subscribe(function (done) {
- createAlerts();
- done();
- });
- },
- };
- $.md.registerGimmick(alertsGimmick);
- // takes a standard <img> tag and adds a hyperlink to the image source
- // needed since we scale down images via css and want them to be accessible
- // in original format
- function createAlerts() {
- var matches = $(select_paragraphs());
- matches.each(function () {
- var $p = $(this.p);
- var type = this.alertType;
- $p.addClass("alert");
- if (type === "note") {
- $p.addClass("alert-info");
- } else if (type === "hint") {
- $p.addClass("alert-success");
- } else if (type === "warning") {
- $p.addClass("alert-warning");
- }
- });
- }
- // picks out the paragraphs that start with a trigger word
- function select_paragraphs() {
- var note = ["note", "beachte"];
- var warning = ["achtung", "attention", "warnung", "warning", "atención", "guarda", "advertimiento"];
- var hint = ["hint", "tipp", "tip", "hinweis"];
- var exp = note.concat(warning);
- exp = exp.concat(hint);
- var matches = [];
- $("p").filter(function () {
- var $par = $(this);
- // check against each expression
- $(exp).each(function (i, trigger) {
- var txt = $par.text().toLowerCase();
- // we match only paragrachps in which the 'trigger' expression
- // is follow by a ! or :
- var re = new RegExp(trigger + "(:|!)+.*", "i");
- var alertType = "none";
- if (txt.match(re) !== null) {
- if ($.inArray(trigger, note) >= 0) {
- alertType = "note";
- } else if ($.inArray(trigger, warning) >= 0) {
- alertType = "warning";
- } else if ($.inArray(trigger, hint) >= 0) {
- alertType = "hint";
- }
- matches.push({
- p: $par,
- alertType: alertType,
- });
- }
- });
- });
- return matches;
- }
- })(jQuery);
- (function ($) {
- // makes trouble, find out why
- //'use strict';
- var colorboxGimmick = {
- name: "colorbox",
- load: function () {
- $.md.stage("gimmick").subscribe(function (done) {
- $.gimmicks("colorbox");
- done();
- });
- },
- };
- $.md.registerGimmick(colorboxGimmick);
- var methods = {
- // takes a standard <img> tag and adds a hyperlink to the image source
- // needed since we scale down images via css and want them to be accessible
- // in original format
- colorbox: function () {
- var $image_groups;
- if (!(this instanceof jQuery)) {
- // select the image groups of the page
- $image_groups = $(".md-image-group");
- } else {
- $image_groups = $(this);
- }
- // operate on md-image-group, which holds one
- // or more images that are to be colorbox'ed
- var counter = 0;
- return $image_groups.each(function () {
- var $this = $(this);
- // each group requires a unique name
- var gal_group = "gallery-group-" + counter++;
- // create a hyperlink around the image
- $this
- .find("a.md-image-selfref img")
- // filter out images that already are a hyperlink
- // (so won't be part of the gallery)
- // apply colorbox on their parent anchors
- .parents("a")
- .colorbox({
- rel: gal_group,
- opacity: 0.75,
- slideshow: true,
- maxWidth: "95%",
- maxHeight: "95%",
- scalePhotos: true,
- photo: true,
- slideshowAuto: false,
- });
- });
- },
- };
- $.gimmicks.methods = $.extend({}, $.fn.gimmicks.methods, methods);
- })(jQuery);
- (function ($) {
- "use strict";
- var themeChooserGimmick = {
- name: "Themes",
- version: $.md.version,
- once: function () {
- $.md.linkGimmick(this, "carousel", carousel);
- },
- };
- $.md.registerGimmick(themeChooserGimmick);
- function carousel($link, opt, href) {
- var $c = $('<div id="myCarousel" class="carousel slide"></div>');
- var $d = $('<div class="carousel-inner"/>');
- $c.append('<ol class="carousel-indicators" />');
- var imageUrls = [];
- var i = 0;
- $.each(href.split(","), function (i, e) {
- imageUrls.push($.trim(e));
- $c.find("ol").append('<li data-target="#myCarousel" data-slide-to="' + i + '" class="active" /');
- var div;
- if (i === 0) {
- div = '<div class="active item"/>';
- } else {
- div = '<div class="item"/>';
- }
- $d.append($(div).append('<img src="' + e + '"/>'));
- });
- $c.append($d);
- $c.append('<a class="carousel-control left" href="#myCarousel" data-slide="prev">‹</a>');
- $c.append('<a class="carousel-control right" href="#myCarousel" data-slide="next">›</a>');
- $link.replaceWith($c);
- }
- })(jQuery);
- (function ($) {
- "use strict";
- var gistGimmick = {
- name: "gist",
- once: function () {
- $.md.linkGimmick(this, "gist", gist);
- },
- };
- $.md.registerGimmick(gistGimmick);
- function gist($links, opt, href) {
- $().lazygist("init");
- return $links.each(function (i, link) {
- var default_options = {
- scheme: "https",
- path: "gist.github.com/",
- };
- var options = $.extend(default_options, opt);
- var $link = $(link);
- var gistDiv = $('<div class="gist_here" data-id="' + href + '" />');
- $link.replaceWith(gistDiv);
- gistDiv.lazygist({
- // we dont want a specific file so modify the url template
- url_template: "{scheme}://{path}{id}.js"
- .replace(/\{scheme\}/g, options.scheme)
- .replace(/\{path\}/g, options.path),
- });
- });
- }
- })(jQuery);
- /**
- * Lazygist v0.2pre
- *
- * a jQuery plugin that will lazy load your gists.
- *
- * since jQuery 1.7.2
- * https://github.com/tammo/jquery-lazy-gist
- *
- * Copyright, Tammo Pape
- * http://tammopape.de
- *
- * Licensed under the MIT license.
- */
- (function ($, window, document, undefined) {
- "use strict";
- //
- // note:
- // this plugin is not stateful
- // and will not communicate with own instances at different elements
- //
- var pluginName = "lazygist",
- version = "0.2pre",
- defaults = {
- // adding the ?file parameter to choose a file
- url_template: "https://gist.github.com/{id}.js?file={file}",
- // if these are strings, the attributes will be read from the element
- id: "data-id",
- file: "data-file",
- },
- options,
- // will be replaced
- /*jshint -W060 */
- originwrite = document.write,
- // stylesheet urls found in document.write calls
- // they are cached to write them once to the document,
- // not three times for three gists
- stylesheets = [],
- // cache gist-ids to know which are already appended to the dom
- ids_dom = [],
- // remember gist-ids if their javascript is already loaded
- ids_ajax = [],
- methods = {
- /**
- * Standard init function
- * No magic here
- */
- init: function (options_input) {
- // default options are default
- options = $.extend({}, defaults, options_input);
- // can be reset
- /*jshint -W061 */
- document.write = _write;
- $.each(options, function (index, value) {
- if (typeof value !== "string") {
- throw new TypeError(value + " (" + typeof value + ") is not a string");
- }
- });
- return this.lazygist("load");
- },
- /**
- * Load the gists
- */
- load: function () {
- // (1) iterate over gist anchors
- // (2) append the gist-html through the new document.write func (see _write)
- // (1)
- return this.filter("[" + options.id + "]").each(function () {
- var id = $(this).attr(options.id),
- file = $(this).attr(options.file),
- src;
- if (id !== undefined) {
- if ($.inArray(id, ids_ajax) !== -1) {
- // just do nothin, if gist is already ajaxed
- return;
- }
- ids_ajax.push(id);
- src = options.url_template.replace(/\{id\}/g, id).replace(/\{file\}/g, file);
- // (2) this will trigger our _write function
- $.getScript(src, function () {});
- }
- });
- },
- /**
- * Just reset the write function
- */
- reset_write: function () {
- document.write = originwrite;
- return this;
- },
- };
- /**
- * private special document.write function
- *
- * Filters the css file from github.com to add it to the head - once -
- *
- * It has a fallback to keep flexibility with other scripts as high as possible
- * (create a ticket if it messes things up!)
- *
- * Keep in mind, that a call to this function happens after
- * an ajax call by jQuery. One *cannot* know which gist-anchor
- * to use. You can only read the id from the content.
- */
- function _write(content) {
- var expression, // for regexp results
- href, // from the url
- id; // from the content
- if (content.indexOf('rel="stylesheet"') !== -1) {
- href = $(content).attr("href");
- // check if stylesheet is already inserted
- if ($.inArray(href, stylesheets) === -1) {
- $("head").append(content);
- stylesheets.push(href);
- }
- } else if (content.indexOf('id="gist') !== -1) {
- // This is the newer gist URL style, ignoring the hostname for GitHub EE instances
- expression = /https?:\/\/gist.*?\/.*\/(.*)#/.exec(content);
- if (expression !== null) {
- id = expression[1];
- } else {
- // This will catch older versions of GitHub EE
- expression = /gist\/.+?\/([a-f0-9]+)\/raw/g.exec(content);
- if (expression !== null) {
- id = expression[1];
- }
- }
- if (id !== undefined) {
- // test if id is already loaded
- if ($.inArray(id, ids_dom) !== -1) {
- // just do nothin, if gist is already attached to the dom
- return;
- }
- ids_dom.push(id);
- $(".gist_here[data-id=" + id + "]").append(content);
- }
- } else {
- // this is a fallback for interoperability
- originwrite.apply(document, arguments);
- }
- }
- // method invocation - from jQuery.com
- $.fn[pluginName] = function (method) {
- if (methods[method]) {
- return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
- } else if (typeof method === "object" || !method) {
- return methods.init.apply(this, arguments);
- } else {
- $.error("Method " + method + " does not exist on jQuery.lazygist");
- }
- };
- // expose version for your interest
- $.fn[pluginName].version = version;
- })(jQuery, window, document);
- (function ($) {
- "use strict";
- var iframeGimmick = {
- name: "iframe",
- version: $.md.version,
- once: function () {
- $.md.linkGimmick(this, "iframe", create_iframe);
- },
- };
- $.md.registerGimmick(iframeGimmick);
- function create_iframe($links, opt, text) {
- return $links.each(function (i, link) {
- var $link = $(link);
- var href = $link.attr("href");
- var $iframe = $('<iframe class="col-md-12" style="border: 0px solid red; height: 650px;"></iframe>');
- $iframe.attr("src", href);
- $link.replaceWith($iframe);
- if (opt.width) $iframe.css("width", opt.width);
- if (opt.height) $iframe.css("height", opt.height);
- else {
- var updateSizeFn = function () {
- var offset = $iframe.offset();
- var winHeight = $(window).height();
- var newHeight = winHeight - offset.top - 5;
- $iframe.height(newHeight);
- };
- $iframe.load(function (done) {
- updateSizeFn();
- });
- $(window).resize(function () {
- updateSizeFn();
- });
- }
- });
- }
- })(jQuery);
- (function ($) {
- var mathGimmick = {
- name: "math",
- once: function () {
- $.md.linkGimmick(this, "math", load_mathjax);
- },
- };
- $.md.registerGimmick(mathGimmick);
- function load_mathjax($links, opt, ref) {
- $links.remove();
- var script = document.createElement("script");
- script.type = "text/javascript";
- script.src = $.md.prepareLink("cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML", {
- forceSSL: true,
- });
- document.getElementsByTagName("head")[0].appendChild(script);
- }
- })(jQuery);
- (function ($) {
- var prismGimmick = {
- name: "prism",
- load: function () {
- $.md.stage("gimmick").subscribe(function (done) {
- prism_highlight();
- done();
- });
- },
- };
- var supportedLangs = [
- "abap",
- "actionscript",
- "apacheconf",
- "apl",
- "applescript",
- "asciidoc",
- "aspnet",
- "autohotkey",
- "autoit",
- "bash",
- "basic",
- "batch",
- "bison",
- "brainfuck",
- "c",
- "clike",
- "coffeescript",
- "core",
- "cpp",
- "crystal",
- "csharp",
- "css",
- "css",
- "d",
- "dart",
- "diff",
- "docker",
- "eiffel",
- "elixir",
- "erlang",
- "fortran",
- "fsharp",
- "gherkin",
- "git",
- "glsl",
- "go",
- "groovy",
- "haml",
- "handlebars",
- "haskell",
- "haxe",
- "http",
- "icon",
- "inform7",
- "ini",
- "j",
- "jade",
- "java",
- "javascript",
- "json",
- "jsx",
- "julia",
- "keyman",
- "kotlin",
- "latex",
- "less",
- "lolcode",
- "lua",
- "makefile",
- "markdown",
- "markup",
- "matlab",
- "mel",
- "mizar",
- "monkey",
- "nasm",
- "nginx",
- "nim",
- "nix",
- "nsis",
- "objectivec",
- "ocaml",
- "oz",
- "parigp",
- "parser",
- "pascal",
- "perl",
- "php",
- "powershell",
- "processing",
- "prolog",
- "puppet",
- "pure",
- "python",
- "q",
- "qore",
- "r",
- "rest",
- "rip",
- "roboconf",
- "ruby",
- "rust",
- "sas",
- "sass",
- "scala",
- "scheme",
- "scss",
- "smalltalk",
- "smarty",
- "sql",
- "stylus",
- "svg",
- "swift",
- "tcl",
- "textile",
- "twig",
- "typescript",
- "verilog",
- "vhdl",
- "vim",
- "wiki",
- "xml",
- "yaml",
- ];
- $.md.registerGimmick(prismGimmick);
- function prism_highlight() {
- // marked adds lang-ruby, lang-csharp etc to the <code> block like in GFM
- var $codeblocks = $("pre code[class^=lang-]");
- $codeblocks.each(function () {
- var $this = $(this);
- var classes = $this.attr("class");
- var lang = classes.substring(5);
- if (supportedLangs.indexOf(lang) < 0) {
- return;
- }
- $this.removeClass(classes);
- $this.addClass("language-" + lang);
- });
- Prism.highlightAll();
- }
- })(jQuery);
- (function ($) {
- "use strict";
- var themes = [
- { name: "bootstrap", url: "netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" },
- { name: "cyborg", url: "netdna.bootstrapcdn.com/bootswatch/3.0.0/cyborg/bootstrap.min.css" },
- { name: "slate", url: "netdna.bootstrapcdn.com/bootswatch/3.0.0/slate/bootstrap.min.css" },
- { name: "darkly", url: "cdn.jsdelivr.net/npm/bootswatch@3.2.0/darkly/bootstrap.min.css" },
- ];
- var useChooser = false;
- var themeChooserGimmick = {
- name: "Themes",
- version: $.md.version,
- once: function () {
- $.md.linkGimmick(this, "themechooser", themechooser, "skel_ready");
- $.md.linkGimmick(this, "theme", apply_theme);
- },
- };
- $.md.registerGimmick(themeChooserGimmick);
- var log = $.md.getLogger();
- var set_theme = function (theme) {
- theme.inverse = theme.inverse || false;
- if (theme.url === undefined) {
- if (!theme.name) {
- log.error("Theme name must be given!");
- return;
- }
- var saved_theme = themes.filter(function (t) {
- return t.name === theme.name;
- })[0];
- if (!saved_theme) {
- log.error("Theme " + name + " not found, removing link");
- return;
- }
- theme = $.extend(theme, saved_theme);
- }
- $('link[rel=stylesheet][href*="netdna.bootstrapcdn.com"]').remove();
- // slim instance has no bootstrap hardcoded in
- var has_default_bootstrap_css = $("style[id*=bootstrap]").length > 0;
- if (theme.name !== "bootstrap" || !has_default_bootstrap_css) {
- // in devel & fat version the style is inlined, remove it
- $("style[id*=bootstrap]").remove();
- $('<link rel="stylesheet" type="text/css">').attr("href", $.md.prepareLink(theme.url)).appendTo("head");
- }
- if (theme.inverse === true) {
- $("#md-main-navbar").removeClass("navbar-default");
- $("#md-main-navbar").addClass("navbar-inverse");
- } else {
- $("#md-main-navbar").addClass("navbar-default");
- $("#md-main-navbar").removeClass("navbar-inverse");
- }
- };
- var apply_theme = function ($links, opt, text) {
- opt.name = opt.name || text;
- $links.each(function (i, link) {
- $.md.stage("postgimmick").subscribe(function (done) {
- var $link = $(link);
- // only set a theme if no theme from the chooser is selected,
- // or if the chooser isn't enabled
- if (window.localStorage.theme === undefined || !useChooser) {
- set_theme(opt);
- }
- done();
- });
- });
- $links.remove();
- };
- var themechooser = function ($links, opt, text) {
- useChooser = true;
- $.md.stage("bootstrap").subscribe(function (done) {
- restore_theme(opt);
- done();
- });
- return $links.each(function (i, e) {
- var $this = $(e);
- var $chooser = $('<a href=""></a><ul></ul>');
- $chooser.eq(0).text(text);
- $.each(themes, function (i, theme) {
- var $li = $("<li></li>");
- $chooser.eq(1).append($li);
- var $a = $("<a/>")
- .text(theme.name)
- .attr("href", "")
- .click(function (ev) {
- ev.preventDefault();
- window.localStorage.theme = theme.name;
- window.location.reload();
- })
- .appendTo($li);
- });
- $chooser.eq(1).append('<li class="divider" />');
- var $li = $("<li/>");
- var $a_use_default = $("<a>Use default</a>");
- $a_use_default.click(function (ev) {
- ev.preventDefault();
- window.localStorage.removeItem("theme");
- window.location.reload();
- });
- $li.append($a_use_default);
- $chooser.eq(1).append($li);
- $this.replaceWith($chooser);
- });
- };
- var restore_theme = function (opt) {
- if (window.localStorage.theme) {
- opt = $.extend({ name: window.localStorage.theme }, opt);
- set_theme(opt);
- }
- };
- })(jQuery);
- (function ($) {
- //'use strict';
- var youtubeGimmick = {
- name: "youtube",
- load: function () {
- $.md.stage("gimmick").subscribe(function (done) {
- youtubeLinkToIframe();
- done();
- });
- },
- };
- $.md.registerGimmick(youtubeGimmick);
- function youtubeLinkToIframe() {
- var $youtube_links = $("a[href*=youtube\\.com]:empty, a[href*=youtu\\.be]:empty");
- $youtube_links.each(function () {
- var $this = $(this);
- var href = $this.attr("href");
- if (href !== undefined) {
- // extract the v parameter from youtube
- var exp = /.*(?:youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=)([^#\&\?]*).*/;
- var m = href.match(exp);
- if (m && m[1].length === 11) {
- // insert the iframe
- var short_handle = m[1];
- var frame = $('<iframe class="md-external" frameborder="0" allowfullscreen></iframe>');
- frame.attr("src", "http://youtube.com/embed/" + short_handle);
- // remove the a tag
- $this.replaceWith(frame);
- }
- }
- });
- }
- })(jQuery);
- (function ($) {
- "use strict";
- var scripturl = "//cdnjs.cloudflare.com/ajax/libs/Chart.js/1.0.2/Chart.min.js";
- var chartGimmick = {
- name: "chart",
- version: $.md.version,
- once: function () {
- $.md.linkGimmick(this, "chart", chart);
- // load the chart js
- $.md.registerScript(this, scripturl, {
- license: "MIT",
- loadstage: "skel_ready",
- finishstage: "gimmick",
- });
- },
- };
- $.md.registerGimmick(chartGimmick);
- var log = $.md.getLogger();
- function chart($links, opt, text) {
- return $links.each(function (i, link) {
- // Get the options for this gimmick
- // labelColumn: This is a string the indicates the column that will be used to
- // label the data points
- // dataColumns: This is a array of strings that indicate each column to be plotted
- // canvasId: This is a ID for the given chart. Defaults to a random number
- // between 1-1000.
- // chartOptions: This is an object that is passed to chartjs to configure its
- // options.
- // chartType: This string is the type of chart we want to render. Bar, Line,
- // or Radar. Defaults to Line.
- var default_options = {
- chartType: "Line",
- canvasId: "chartGimmick" + Math.floor(Math.random() * 1000 + 1),
- chartOptions: {
- responsive: false,
- },
- };
- var options = $.extend({}, default_options, opt);
- var $link = $(link);
- var table = $link.parents().find("table").last();
- if (table.length === 0) {
- log.error("Chart Gimmick: No tables found on the page.");
- $link.remove();
- return;
- }
- // Replace the Gimmick with the canvas that chartJS needs
- var myHtml = $('<canvas id="' + options.canvasId + '"></canvas>');
- myHtml.width(options.width || "450px");
- myHtml.height(options.height || "250px");
- $link.replaceWith(myHtml);
- // This is the object that is given to the chart frame work for rendering. It will be
- // built up by processing the html table that is found on the table.
- var chartConfig = {
- datasets: [],
- labels: [],
- };
- var chartAvailableToRender = true;
- // These variables hold the indices of the columns in the table we care about. They will
- // be populated as we process the table based on the options that are given in the
- // gimmick
- var labelColumnIndex = -1;
- var dataColumnIndices = [];
- // Get the index of the columns that we care about for charting
- table.find("th").each(function (index) {
- // This is the column that labels each data point
- if (this.textContent === options.labelColumn) {
- labelColumnIndex = index;
- }
- // Check if this is a data column
- else {
- for (var i = 0; i < options.dataColumns.length; i++) {
- if (this.textContent === options.dataColumns[i]) {
- dataColumnIndices.push(index);
- }
- }
- }
- });
- // Get the data
- table.find("tr").each(function (rowIndex) {
- $(this)
- .find("td")
- .each(function (colIndex) {
- if (colIndex === labelColumnIndex) {
- chartConfig.labels.push(this.textContent);
- } else {
- for (var i = 0; i < dataColumnIndices.length; i++) {
- if (colIndex === dataColumnIndices[i]) {
- if (chartConfig.datasets[i] === undefined) {
- chartConfig.datasets[i] = {};
- chartConfig.datasets[i].data = [];
- }
- chartConfig.datasets[i].data.push(this.textContent);
- }
- }
- }
- });
- });
- // No Chart data found
- if (chartConfig.datasets[i] === undefined) {
- chartAvailableToRender = false;
- log.error(
- "Chart Gimmick: No data was found for the chart. Make sure that there " +
- "is a tables on the page. Check that your " +
- "column headers match the chart configuration."
- );
- }
- if (chartAvailableToRender) {
- var canvas = document.getElementById(options.canvasId);
- var ctx = canvas.getContext("2d");
- $.md.stage("postgimmick").subscribe(function (done) {
- setTimeout(function () {
- new Chart(ctx)[options.chartType](chartConfig, options.chartOptions);
- });
- done();
- });
- }
- });
- }
- })(jQuery);
- (function ($) {
- "use strict";
- function yuml($link, opt, text) {
- var default_options = {
- type: "class" /* { class, activity, usecase } */,
- style: "plain" /* { plain, scruffy } */,
- direction: "LR" /* LR, TB, RL */,
- scale: "100",
- };
- var options = $.extend({}, default_options, opt);
- return $link.each(function (i, e) {
- var $this = $(e);
- var url = "http://yuml.me/diagram/";
- var data = $this.attr("href");
- var title = $this.attr("title");
- title = title ? title : "";
- /* `FOOBAR´ => (FOOBAR) */
- data = data.replace(new RegExp("`", "g"), "(").replace(new RegExp("´", "g"), ")");
- url +=
- options.style +
- ";dir:" +
- options.direction +
- ";scale:" +
- options.scale +
- "/" +
- options.type +
- "/" +
- data;
- var $img = $('<img src="' + url + '" title="' + title + '" alt="' + title + '">');
- $this.replaceWith($img);
- });
- }
- var yumlGimmick = {
- name: "yuml",
- version: $.md.version,
- once: function () {
- $.md.linkGimmick(this, "yuml", yuml);
- $.md.registerScript(this, "", {
- license: "LGPL",
- loadstage: "postgimmick",
- finishstage: "all_ready",
- });
- },
- };
- $.md.registerGimmick(yumlGimmick);
- })(jQuery);
|