├── .gitattributes ├── app ├── robots.txt ├── favicon.ico ├── scripts │ ├── collection │ │ └── LibraryCollection.js │ ├── component │ │ ├── AboutComponent.react.js │ │ ├── IndexComponent.react.js │ │ ├── ProjectComponent.react.js │ │ ├── ProductComponent.react.js │ │ ├── MenuComponent.react.js │ │ └── LibraryComponent.react.js │ ├── model │ │ ├── UserModel.js │ │ └── LibraryModel.js │ ├── data │ │ ├── navigation.js │ │ └── libraries.js │ ├── main.js │ ├── app.react.js │ ├── vendor │ │ ├── jquery.touchwipe.min.js │ │ ├── mdown.js │ │ ├── json.js │ │ ├── jsx.js │ │ ├── jquery.sidr.min.js │ │ ├── react.backbone.js │ │ ├── text.js │ │ ├── lodash.min.js │ │ └── Markdown.Converter.js │ └── router.react.js └── styles │ ├── grids-responsive-old-ie-min.css │ ├── main.css │ └── pure-min.css ├── .bowerrc ├── test ├── .bowerrc ├── bower.json ├── spec │ └── test.js └── index.html ├── .gitignore ├── .yo-rc.json ├── .editorconfig ├── bower.json ├── README.md ├── .jshintrc ├── package.json ├── index.html └── Gruntfile.js /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto -------------------------------------------------------------------------------- /app/robots.txt: -------------------------------------------------------------------------------- 1 | # robotstxt.org 2 | 3 | User-agent: * 4 | -------------------------------------------------------------------------------- /.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "app/bower_components" 3 | } 4 | -------------------------------------------------------------------------------- /test/.bowerrc: -------------------------------------------------------------------------------- 1 | { 2 | "directory": "bower_components" 3 | } 4 | -------------------------------------------------------------------------------- /app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phodal/backbone-react/gh-pages/app/favicon.ico -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | test/temp 4 | .sass-cache 5 | app/bower_components 6 | .tmp 7 | test/bower_components/ 8 | .idea/ 9 | -------------------------------------------------------------------------------- /test/bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "backbone-react", 3 | "private": true, 4 | "dependencies": { 5 | "chai": "~1.8.0", 6 | "mocha": "~1.14.0" 7 | }, 8 | "devDependencies": {} 9 | } 10 | -------------------------------------------------------------------------------- /app/scripts/collection/LibraryCollection.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | define(['backbone', '../model/LibraryModel'], function(Backbone, LibraryModel) { 4 | var LibraryCollection = Backbone.Collection.extend({ 5 | model: LibraryModel 6 | }); 7 | 8 | return LibraryCollection; 9 | }); 10 | -------------------------------------------------------------------------------- /.yo-rc.json: -------------------------------------------------------------------------------- 1 | { 2 | "generator-backbone": { 3 | "appPath": "app", 4 | "appName": "BackboneReact", 5 | "coffee": false, 6 | "testFramework": "mocha", 7 | "templateFramework": "lodash", 8 | "sassBootstrap": false, 9 | "includeRequireJS": true 10 | }, 11 | "generator-mocha": {} 12 | } -------------------------------------------------------------------------------- /app/scripts/component/AboutComponent.react.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | define([ 4 | 'react' 5 | ],function(React){ 6 | return React.createClass({ 7 | render: function () { 8 | return
f(h,y))&&((u||v)&&h.push(y),s.push(g))}return v?(l(h.k),c(h)):u&&l(h),s}function lt(n){return function(t,e,r){var u={};e=J.createCallback(e,r,3),r=-1;var o=t?t.length:0;if(typeof o=="number")for(;++r s around
263 | // "paragraphs" that are wrapped in non-block-level tags, such as anchors,
264 | // phrase emphasis, and spans. The list of tags we're looking for is
265 | // hard-coded:
266 | var block_tags_a = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del"
267 | var block_tags_b = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math"
268 |
269 | // First, look for nested blocks, e.g.:
270 | // tags around block-level tags.
415 | text = _HashHTMLBlocks(text);
416 | text = _FormParagraphs(text, doNotUnhash);
417 |
418 | return text;
419 | }
420 |
421 | function _RunSpanGamut(text) {
422 | //
423 | // These are all the transformations that occur *within* block-level
424 | // tags like paragraphs, headers, and list items.
425 | //
426 |
427 | text = _DoCodeSpans(text);
428 | text = _EscapeSpecialCharsWithinTagAttributes(text);
429 | text = _EncodeBackslashEscapes(text);
430 |
431 | // Process anchor and image tags. Images must come first,
432 | // because ![foo][f] looks like an anchor.
433 | text = _DoImages(text);
434 | text = _DoAnchors(text);
435 |
436 | // Make links out of things like ` Just type tags
1127 | //
1128 |
1129 | // Strip leading and trailing lines:
1130 | text = text.replace(/^\n+/g, "");
1131 | text = text.replace(/\n+$/g, "");
1132 |
1133 | var grafs = text.split(/\n{2,}/g);
1134 | var grafsOut = [];
1135 |
1136 | var markerRe = /~K(\d+)K/;
1137 |
1138 | //
1139 | // Wrap tags.
1140 | //
1141 | var end = grafs.length;
1142 | for (var i = 0; i < end; i++) {
1143 | var str = grafs[i];
1144 |
1145 | // if this is an HTML marker, copy it
1146 | if (markerRe.test(str)) {
1147 | grafsOut.push(str);
1148 | }
1149 | else if (/\S/.test(str)) {
1150 | str = _RunSpanGamut(str);
1151 | str = str.replace(/^([ \t]*)/g, " ");
1152 | str += " tags get encoded.
142 | //
143 |
144 | // This will only happen if makeHtml on the same converter instance is called from a plugin hook.
145 | // Don't do that.
146 | if (g_urls)
147 | throw new Error("Recursive call to converter.makeHtml");
148 |
149 | // Create the private state objects.
150 | g_urls = new SaveHash();
151 | g_titles = new SaveHash();
152 | g_html_blocks = [];
153 | g_list_level = 0;
154 |
155 | text = pluginHooks.preConversion(text);
156 |
157 | // attacklab: Replace ~ with ~T
158 | // This lets us use tilde as an escape char to avoid md5 hashes
159 | // The choice of character is arbitray; anything that isn't
160 | // magic in Markdown will work.
161 | text = text.replace(/~/g, "~T");
162 |
163 | // attacklab: Replace $ with ~D
164 | // RegExp interprets $ as a special character
165 | // when it's in a replacement string
166 | text = text.replace(/\$/g, "~D");
167 |
168 | // Standardize line endings
169 | text = text.replace(/\r\n/g, "\n"); // DOS to Unix
170 | text = text.replace(/\r/g, "\n"); // Mac to Unix
171 |
172 | // Make sure text begins and ends with a couple of newlines:
173 | text = "\n\n" + text + "\n\n";
174 |
175 | // Convert all tabs to spaces.
176 | text = _Detab(text);
177 |
178 | // Strip any lines consisting only of spaces and tabs.
179 | // This makes subsequent regexen easier to write, because we can
180 | // match consecutive blank lines with /\n+/ instead of something
181 | // contorted like /[ \t]*\n+/ .
182 | text = text.replace(/^[ \t]+$/mg, "");
183 |
184 | // Turn block-level HTML blocks into hash entries
185 | text = _HashHTMLBlocks(text);
186 |
187 | // Strip link definitions, store in hashes.
188 | text = _StripLinkDefinitions(text);
189 |
190 | text = _RunBlockGamut(text);
191 |
192 | text = _UnescapeSpecialChars(text);
193 |
194 | // attacklab: Restore dollar signs
195 | text = text.replace(/~D/g, "$$");
196 |
197 | // attacklab: Restore tildes
198 | text = text.replace(/~T/g, "~");
199 |
200 | text = pluginHooks.postConversion(text);
201 |
202 | g_html_blocks = g_titles = g_urls = null;
203 |
204 | return text;
205 | };
206 |
207 | function _StripLinkDefinitions(text) {
208 | //
209 | // Strips link definitions from text, stores the URLs and titles in
210 | // hash references.
211 | //
212 |
213 | // Link defs are in the form: ^[id]: url "optional title"
214 |
215 | /*
216 | text = text.replace(/
217 | ^[ ]{0,3}\[(.+)\]: // id = $1 attacklab: g_tab_width - 1
218 | [ \t]*
219 | \n? // maybe *one* newline
220 | [ \t]*
221 | (\S+?)>? // url = $2
222 | (?=\s|$) // lookahead for whitespace instead of the lookbehind removed below
223 | [ \t]*
224 | \n? // maybe one newline
225 | [ \t]*
226 | ( // (potential) title = $3
227 | (\n*) // any lines skipped = $4 attacklab: lookbehind removed
228 | [ \t]+
229 | ["(]
230 | (.+?) // title = $5
231 | [")]
232 | [ \t]*
233 | )? // title is optional
234 | (?:\n+|$)
235 | /gm, function(){...});
236 | */
237 |
238 | text = text.replace(/^[ ]{0,3}\[(.+)\]:[ \t]*\n?[ \t]*(\S+?)>?(?=\s|$)[ \t]*\n?[ \t]*((\n*)["(](.+?)[")][ \t]*)?(?:\n+)/gm,
239 | function (wholeMatch, m1, m2, m3, m4, m5) {
240 | m1 = m1.toLowerCase();
241 | g_urls.set(m1, _EncodeAmpsAndAngles(m2)); // Link IDs are case-insensitive
242 | if (m4) {
243 | // Oops, found blank lines, so it's not a title.
244 | // Put back the parenthetical statement we stole.
245 | return m3;
246 | } else if (m5) {
247 | g_titles.set(m1, m5.replace(/"/g, """));
248 | }
249 |
250 | // Completely remove the definition from the text
251 | return "";
252 | }
253 | );
254 |
255 | return text;
256 | }
257 |
258 | function _HashHTMLBlocks(text) {
259 |
260 | // Hashify HTML blocks:
261 | // We only want to do this for block-level HTML tags, such as headers,
262 | // lists, and tables. That's because we still want to wrap
. It was easier to make a special case than
320 | // to make the other regex more complicated.
321 |
322 | /*
323 | text = text.replace(/
324 | \n // Starting after a blank line
325 | [ ]{0,3}
326 | ( // save in $1
327 | (<(hr) // start tag = $2
328 | \b // word break
329 | ([^<>])*?
330 | \/?>) // the matching end tag
331 | [ \t]*
332 | (?=\n{2,}) // followed by a blank line
333 | )
334 | /g,hashElement);
335 | */
336 | text = text.replace(/\n[ ]{0,3}((<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g, hashElement);
337 |
338 | // Special case for standalone HTML comments:
339 |
340 | /*
341 | text = text.replace(/
342 | \n\n // Starting after a blank line
343 | [ ]{0,3} // attacklab: g_tab_width - 1
344 | ( // save in $1
345 | -]|-[^>])(?:[^-]|-[^-])*)--) // see http://www.w3.org/TR/html-markup/syntax.html#comments and http://meta.stackoverflow.com/q/95256
347 | >
348 | [ \t]*
349 | (?=\n{2,}) // followed by a blank line
350 | )
351 | /g,hashElement);
352 | */
353 | text = text.replace(/\n\n[ ]{0,3}(-]|-[^>])(?:[^-]|-[^-])*)--)>[ \t]*(?=\n{2,}))/g, hashElement);
354 |
355 | // PHP and ASP-style processor instructions (...?> and <%...%>)
356 |
357 | /*
358 | text = text.replace(/
359 | (?:
360 | \n\n // Starting after a blank line
361 | )
362 | ( // save in $1
363 | [ ]{0,3} // attacklab: g_tab_width - 1
364 | (?:
365 | <([?%]) // $2
366 | [^\r]*?
367 | \2>
368 | )
369 | [ \t]*
370 | (?=\n{2,}) // followed by a blank line
371 | )
372 | /g,hashElement);
373 | */
374 | text = text.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g, hashElement);
375 |
376 | return text;
377 | }
378 |
379 | function hashElement(wholeMatch, m1) {
380 | var blockText = m1;
381 |
382 | // Undo double lines
383 | blockText = blockText.replace(/^\n+/, "");
384 |
385 | // strip trailing blank lines
386 | blockText = blockText.replace(/\n+$/g, "");
387 |
388 | // Replace the element text with a marker ("~KxK" where x is its key)
389 | blockText = "\n\n~K" + (g_html_blocks.push(blockText) - 1) + "K\n\n";
390 |
391 | return blockText;
392 | }
393 |
394 | function _RunBlockGamut(text, doNotUnhash) {
395 | //
396 | // These are all the transformations that form block-level
397 | // tags like paragraphs, headers, and list items.
398 | //
399 | text = _DoHeaders(text);
400 |
401 | // Do Horizontal Rules:
402 | var replacement = "
\n";
403 | text = text.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm, replacement);
404 | text = text.replace(/^[ ]{0,2}([ ]?-[ ]?){3,}[ \t]*$/gm, replacement);
405 | text = text.replace(/^[ ]{0,2}([ ]?_[ ]?){3,}[ \t]*$/gm, replacement);
406 |
407 | text = _DoLists(text);
408 | text = _DoCodeBlocks(text);
409 | text = _DoBlockQuotes(text);
410 |
411 | // We already ran _HashHTMLBlocks() before, in Markdown(), but that
412 | // was to escape raw HTML in the original Markdown source. This time,
413 | // we're escaping the markup we've just created, so that we don't wrap
414 | //
\n");
448 |
449 | return text;
450 | }
451 |
452 | function _EscapeSpecialCharsWithinTagAttributes(text) {
453 | //
454 | // Within tags -- meaning between < and > -- encode [\ ` * _] so they
455 | // don't conflict with their use in Markdown for code, italics and strong.
456 | //
457 |
458 | // Build a regex to find HTML tags and comments. See Friedl's
459 | // "Mastering Regular Expressions", 2nd Ed., pp. 200-201.
460 |
461 | // SE: changed the comment part of the regex
462 |
463 | var regex = /(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|-]|-[^>])(?:[^-]|-[^-])*)--)>)/gi;
464 |
465 | text = text.replace(regex, function (wholeMatch) {
466 | var tag = wholeMatch.replace(/(.)<\/?code>(?=.)/g, "$1`");
467 | tag = escapeCharacters(tag, wholeMatch.charAt(1) == "!" ? "\\`*_/" : "\\`*_"); // also escape slashes in comments to prevent autolinking there -- http://meta.stackoverflow.com/questions/95987
468 | return tag;
469 | });
470 |
471 | return text;
472 | }
473 |
474 | function _DoAnchors(text) {
475 | //
476 | // Turn Markdown link shortcuts into XHTML tags.
477 | //
478 | //
479 | // First, handle reference-style links: [link text] [id]
480 | //
481 |
482 | /*
483 | text = text.replace(/
484 | ( // wrap whole match in $1
485 | \[
486 | (
487 | (?:
488 | \[[^\]]*\] // allow brackets nested one level
489 | |
490 | [^\[] // or anything else
491 | )*
492 | )
493 | \]
494 |
495 | [ ]? // one optional space
496 | (?:\n[ ]*)? // one optional newline followed by spaces
497 |
498 | \[
499 | (.*?) // id = $3
500 | \]
501 | )
502 | ()()()() // pad remaining backreferences
503 | /g, writeAnchorTag);
504 | */
505 | text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, writeAnchorTag);
506 |
507 | //
508 | // Next, inline-style links: [link text](url "optional title")
509 | //
510 |
511 | /*
512 | text = text.replace(/
513 | ( // wrap whole match in $1
514 | \[
515 | (
516 | (?:
517 | \[[^\]]*\] // allow brackets nested one level
518 | |
519 | [^\[\]] // or anything else
520 | )*
521 | )
522 | \]
523 | \( // literal paren
524 | [ \t]*
525 | () // no id, so leave $3 empty
526 | ( // href = $4
527 | (?:
528 | \([^)]*\) // allow one level of (correctly nested) parens (think MSDN)
529 | |
530 | [^()]
531 | )*?
532 | )>?
533 | [ \t]*
534 | ( // $5
535 | (['"]) // quote char = $6
536 | (.*?) // Title = $7
537 | \6 // matching quote
538 | [ \t]* // ignore any spaces/tabs between closing quote and )
539 | )? // title is optional
540 | \)
541 | )
542 | /g, writeAnchorTag);
543 | */
544 |
545 | text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()((?:\([^)]*\)|[^()])*?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, writeAnchorTag);
546 |
547 | //
548 | // Last, handle reference-style shortcuts: [link text]
549 | // These must come last in case you've also got [link test][1]
550 | // or [link test](/foo)
551 | //
552 |
553 | /*
554 | text = text.replace(/
555 | ( // wrap whole match in $1
556 | \[
557 | ([^\[\]]+) // link text = $2; can't contain '[' or ']'
558 | \]
559 | )
560 | ()()()()() // pad rest of backreferences
561 | /g, writeAnchorTag);
562 | */
563 | text = text.replace(/(\[([^\[\]]+)\])()()()()()/g, writeAnchorTag);
564 |
565 | return text;
566 | }
567 |
568 | function writeAnchorTag(wholeMatch, m1, m2, m3, m4, m5, m6, m7) {
569 | if (m7 == undefined) m7 = "";
570 | var whole_match = m1;
571 | var link_text = m2.replace(/:\/\//g, "~P"); // to prevent auto-linking withing the link. will be converted back after the auto-linker runs
572 | var link_id = m3.toLowerCase();
573 | var url = m4;
574 | var title = m7;
575 |
576 | if (url == "") {
577 | if (link_id == "") {
578 | // lower-case and turn embedded newlines into spaces
579 | link_id = link_text.toLowerCase().replace(/ ?\n/g, " ");
580 | }
581 | url = "#" + link_id;
582 |
583 | if (g_urls.get(link_id) != undefined) {
584 | url = g_urls.get(link_id);
585 | if (g_titles.get(link_id) != undefined) {
586 | title = g_titles.get(link_id);
587 | }
588 | }
589 | else {
590 | if (whole_match.search(/\(\s*\)$/m) > -1) {
591 | // Special case for explicit empty url
592 | url = "";
593 | } else {
594 | return whole_match;
595 | }
596 | }
597 | }
598 | url = encodeProblemUrlChars(url);
599 | url = escapeCharacters(url, "*_");
600 | var result = "" + link_text + "";
609 |
610 | return result;
611 | }
612 |
613 | function _DoImages(text) {
614 | //
615 | // Turn Markdown image shortcuts into tags.
616 | //
617 |
618 | //
619 | // First, handle reference-style labeled images: ![alt text][id]
620 | //
621 |
622 | /*
623 | text = text.replace(/
624 | ( // wrap whole match in $1
625 | !\[
626 | (.*?) // alt text = $2
627 | \]
628 |
629 | [ ]? // one optional space
630 | (?:\n[ ]*)? // one optional newline followed by spaces
631 |
632 | \[
633 | (.*?) // id = $3
634 | \]
635 | )
636 | ()()()() // pad rest of backreferences
637 | /g, writeImageTag);
638 | */
639 | text = text.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, writeImageTag);
640 |
641 | //
642 | // Next, handle inline images: 
643 | // Don't forget: encode * and _
644 |
645 | /*
646 | text = text.replace(/
647 | ( // wrap whole match in $1
648 | !\[
649 | (.*?) // alt text = $2
650 | \]
651 | \s? // One optional whitespace character
652 | \( // literal paren
653 | [ \t]*
654 | () // no id, so leave $3 empty
655 | (\S+?)>? // src url = $4
656 | [ \t]*
657 | ( // $5
658 | (['"]) // quote char = $6
659 | (.*?) // title = $7
660 | \6 // matching quote
661 | [ \t]*
662 | )? // title is optional
663 | \)
664 | )
665 | /g, writeImageTag);
666 | */
667 | text = text.replace(/(!\[(.*?)\]\s?\([ \t]*()(\S+?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, writeImageTag);
668 |
669 | return text;
670 | }
671 |
672 | function attributeEncode(text) {
673 | // unconditionally replace angle brackets here -- what ends up in an attribute (e.g. alt or title)
674 | // never makes sense to have verbatim HTML in it (and the sanitizer would totally break it)
675 | return text.replace(/>/g, ">").replace(/
" + _RunSpanGamut(m1) + "
\n\n"; }
734 | );
735 |
736 | text = text.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm,
737 | function (matchFound, m1) { return "" + _RunSpanGamut(m1) + "
\n\n"; }
738 | );
739 |
740 | // atx-style headers:
741 | // # Header 1
742 | // ## Header 2
743 | // ## Header 2 with closing hashes ##
744 | // ...
745 | // ###### Header 6
746 | //
747 |
748 | /*
749 | text = text.replace(/
750 | ^(\#{1,6}) // $1 = string of #'s
751 | [ \t]*
752 | (.+?) // $2 = Header text
753 | [ \t]*
754 | \#* // optional closing #'s (not counted)
755 | \n+
756 | /gm, function() {...});
757 | */
758 |
759 | text = text.replace(/^(\#{1,6})[ \t]*(.+?)[ \t]*\#*\n+/gm,
760 | function (wholeMatch, m1, m2) {
761 | var h_level = m1.length;
762 | return "` blocks.
935 | //
936 |
937 | /*
938 | text = text.replace(/
939 | (?:\n\n|^)
940 | ( // $1 = the code block -- one or more lines, starting with a space/tab
941 | (?:
942 | (?:[ ]{4}|\t) // Lines must start with a tab or a tab-width of spaces - attacklab: g_tab_width
943 | .*\n+
944 | )+
945 | )
946 | (\n*[ ]{0,3}[^ \t\n]|(?=~0)) // attacklab: g_tab_width
947 | /g ,function(){...});
948 | */
949 |
950 | // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
951 | text += "~0";
952 |
953 | text = text.replace(/(?:\n\n|^)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g,
954 | function (wholeMatch, m1, m2) {
955 | var codeblock = m1;
956 | var nextChar = m2;
957 |
958 | codeblock = _EncodeCode(_Outdent(codeblock));
959 | codeblock = _Detab(codeblock);
960 | codeblock = codeblock.replace(/^\n+/g, ""); // trim leading newlines
961 | codeblock = codeblock.replace(/\n+$/g, ""); // trim trailing whitespace
962 |
963 | codeblock = "
";
964 |
965 | return "\n\n" + codeblock + "\n\n" + nextChar;
966 | }
967 | );
968 |
969 | // attacklab: strip sentinel
970 | text = text.replace(/~0/, "");
971 |
972 | return text;
973 | }
974 |
975 | function hashBlock(text) {
976 | text = text.replace(/(^\n+|\n+$)/g, "");
977 | return "\n\n~K" + (g_html_blocks.push(text) - 1) + "K\n\n";
978 | }
979 |
980 | function _DoCodeSpans(text) {
981 | //
982 | // * Backtick quotes are used for " + codeblock + "\n spans.
983 | //
984 | // * You can use multiple backticks as the delimiters if you want to
985 | // include literal backticks in the code span. So, this input:
986 | //
987 | // Just type ``foo `bar` baz`` at the prompt.
988 | //
989 | // Will translate to:
990 | //
991 | // foo `bar` baz at the prompt.`bar` ...
1004 | //
1005 |
1006 | /*
1007 | text = text.replace(/
1008 | (^|[^\\]) // Character before opening ` can't be a backslash
1009 | (`+) // $2 = Opening run of `
1010 | ( // $3 = The code block
1011 | [^\r]*?
1012 | [^`] // attacklab: work around lack of lookbehind
1013 | )
1014 | \2 // Matching closer
1015 | (?!`)
1016 | /gm, function(){...});
1017 | */
1018 |
1019 | text = text.replace(/(^|[^\\])(`+)([^\r]*?[^`])\2(?!`)/gm,
1020 | function (wholeMatch, m1, m2, m3, m4) {
1021 | var c = m3;
1022 | c = c.replace(/^([ \t]*)/g, ""); // leading whitespace
1023 | c = c.replace(/[ \t]*$/g, ""); // trailing whitespace
1024 | c = _EncodeCode(c);
1025 | c = c.replace(/:\/\//g, "~P"); // to prevent auto-linking. Not necessary in code *blocks*, but in code spans. Will be converted back after the auto-linker runs.
1026 | return m1 + "" + c + "";
1027 | }
1028 | );
1029 |
1030 | return text;
1031 | }
1032 |
1033 | function _EncodeCode(text) {
1034 | //
1035 | // Encode/escape certain characters inside Markdown code runs.
1036 | // The point is that in code, these characters are literals,
1037 | // and lose their special Markdown meanings.
1038 | //
1039 | // Encode all ampersands; HTML entities are not
1040 | // entities within a Markdown code span.
1041 | text = text.replace(/&/g, "&");
1042 |
1043 | // Do the angle bracket song and dance:
1044 | text = text.replace(//g, ">");
1046 |
1047 | // Now, escape characters that are magic in Markdown:
1048 | text = escapeCharacters(text, "\*_{}[]\\", false);
1049 |
1050 | // jj the line above breaks this:
1051 | //---
1052 |
1053 | //* Item
1054 |
1055 | // 1. Subitem
1056 |
1057 | // special char: *
1058 | //---
1059 |
1060 | return text;
1061 | }
1062 |
1063 | function _DoItalicsAndBold(text) {
1064 |
1065 | // must go first:
1066 | text = text.replace(/([\W_]|^)(\*\*|__)(?=\S)([^\r]*?\S[\*_]*)\2([\W_]|$)/g,
1067 | "$1$3$4");
1068 |
1069 | text = text.replace(/([\W_]|^)(\*|_)(?=\S)([^\r\*_]*?\S)\2([\W_]|$)/g,
1070 | "$1$3$4");
1071 |
1072 | return text;
1073 | }
1074 |
1075 | function _DoBlockQuotes(text) {
1076 |
1077 | /*
1078 | text = text.replace(/
1079 | ( // Wrap whole match in $1
1080 | (
1081 | ^[ \t]*>[ \t]? // '>' at the start of a line
1082 | .+\n // rest of the first line
1083 | (.+\n)* // subsequent consecutive lines
1084 | \n* // blanks
1085 | )+
1086 | )
1087 | /gm, function(){...});
1088 | */
1089 |
1090 | text = text.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm,
1091 | function (wholeMatch, m1) {
1092 | var bq = m1;
1093 |
1094 | // attacklab: hack around Konqueror 3.5.4 bug:
1095 | // "----------bug".replace(/^-/g,"") == "bug"
1096 |
1097 | bq = bq.replace(/^[ \t]*>[ \t]?/gm, "~0"); // trim one level of quoting
1098 |
1099 | // attacklab: clean up hack
1100 | bq = bq.replace(/~0/g, "");
1101 |
1102 | bq = bq.replace(/^[ \t]+$/gm, ""); // trim whitespace-only lines
1103 | bq = _RunBlockGamut(bq); // recurse
1104 |
1105 | bq = bq.replace(/(^|\n)/g, "$1 ");
1106 | // These leading spaces screw with content, so we need to fix that:
1107 | bq = bq.replace(
1108 | /(\s*
[^\r]+?<\/pre>)/gm,
1109 | function (wholeMatch, m1) {
1110 | var pre = m1;
1111 | // attacklab: hack around Konqueror 3.5.4 bug:
1112 | pre = pre.replace(/^ /mg, "~0");
1113 | pre = pre.replace(/~0/g, "");
1114 | return pre;
1115 | });
1116 |
1117 | return hashBlock("\n" + bq + "\n
");
1118 | }
1119 | );
1120 | return text;
1121 | }
1122 |
1123 | function _FormParagraphs(text, doNotUnhash) {
1124 | //
1125 | // Params:
1126 | // $text - string to process with html