diff --git a/roles/0-DEPRECATED-ROLES/activity-server/tasks/main.yml b/roles/0-DEPRECATED-ROLES/activity-server/tasks/main.yml index 61d4b6baa..d2e59dc6b 100644 --- a/roles/0-DEPRECATED-ROLES/activity-server/tasks/main.yml +++ b/roles/0-DEPRECATED-ROLES/activity-server/tasks/main.yml @@ -80,7 +80,7 @@ # SEE ALSO THE apache2_module SECTION IN roles/httpd/tasks/main.yml - name: enable mod_expires for debian command: a2enmod expires - when: is_debuntu | bool + when: is_debuntu - name: create the link which enables the site file: src=/etc/apache2/sites-available/xs-activity-server.conf diff --git a/roles/0-DEPRECATED-ROLES/ajenti/tasks/ajenti-wondershaper.yml b/roles/0-DEPRECATED-ROLES/ajenti/tasks/ajenti-wondershaper.yml index 76713a470..4b4d28fe1 100644 --- a/roles/0-DEPRECATED-ROLES/ajenti/tasks/ajenti-wondershaper.yml +++ b/roles/0-DEPRECATED-ROLES/ajenti/tasks/ajenti-wondershaper.yml @@ -1,3 +1,3 @@ - name: Install wondershaper ajenti plugin pip: name="{{ iiab_download_url }}"/ajenti-plugin-wondershaper-0.3.tar.gz - when: internet_available | bool + when: internet_available diff --git a/roles/0-DEPRECATED-ROLES/ajenti/tasks/main.yml b/roles/0-DEPRECATED-ROLES/ajenti/tasks/main.yml index 9dd6def11..156656b0f 100644 --- a/roles/0-DEPRECATED-ROLES/ajenti/tasks/main.yml +++ b/roles/0-DEPRECATED-ROLES/ajenti/tasks/main.yml @@ -45,7 +45,7 @@ service: name=ajenti enabled=yes state=restarted - when: ajenti_enabled | bool + when: ajenti_enabled - name: Add 'ajenti' variable values to {{ iiab_ini_file }} ini_file: diff --git a/roles/0-DEPRECATED-ROLES/authserver/tasks/main.yml b/roles/0-DEPRECATED-ROLES/authserver/tasks/main.yml index 6742c9d4e..614374519 100644 --- a/roles/0-DEPRECATED-ROLES/authserver/tasks/main.yml +++ b/roles/0-DEPRECATED-ROLES/authserver/tasks/main.yml @@ -4,7 +4,7 @@ - name: Install xs-authserver from pypi pip: name=xs-authserver - when: internet_available | bool + when: internet_available - name: install gunicorn package: name=python-gunicorn @@ -48,7 +48,7 @@ service: name=xs-authserver state=restarted enabled=yes - when: authserver_enabled | bool + when: authserver_enabled - name: Add 'authserver' variable values to {{ iiab_ini_file }} ini_file: diff --git a/roles/0-DEPRECATED-ROLES/docker/tasks/main.yml b/roles/0-DEPRECATED-ROLES/docker/tasks/main.yml index 8c890c7d8..a51f1b8bd 100644 --- a/roles/0-DEPRECATED-ROLES/docker/tasks/main.yml +++ b/roles/0-DEPRECATED-ROLES/docker/tasks/main.yml @@ -4,7 +4,7 @@ with_items: - docker - python-docker-py - when: docker_install | bool + when: docker_install - name: put the systemd startup file in place template: src=docker.service @@ -31,7 +31,7 @@ service: name=docker state=started enabled=true - when: docker_enabled | bool + when: docker_enabled - name: Disable docker service: name=docker diff --git a/roles/0-DEPRECATED-ROLES/dokuwiki/tasks/enable.yml b/roles/0-DEPRECATED-ROLES/dokuwiki/tasks/enable.yml index 45e08a407..094312866 100644 --- a/roles/0-DEPRECATED-ROLES/dokuwiki/tasks/enable.yml +++ b/roles/0-DEPRECATED-ROLES/dokuwiki/tasks/enable.yml @@ -12,7 +12,7 @@ systemd: name: "{{ apache_service }}" state: restarted - when: apache_enabled | bool + when: apache_enabled # NGINX @@ -32,7 +32,7 @@ systemd: name: nginx state: restarted - when: nginx_enabled | bool + when: nginx_enabled - name: Add 'dokuwiki' variable values to {{ iiab_ini_file }} diff --git a/roles/0-DEPRECATED-ROLES/dokuwiki/tasks/install.yml b/roles/0-DEPRECATED-ROLES/dokuwiki/tasks/install.yml index a640a4deb..00625eff5 100644 --- a/roles/0-DEPRECATED-ROLES/dokuwiki/tasks/install.yml +++ b/roles/0-DEPRECATED-ROLES/dokuwiki/tasks/install.yml @@ -3,7 +3,7 @@ url: "{{ iiab_download_url }}/{{ dokuwiki_version }}.tgz" dest: "{{ downloads_dir }}/" timeout: "{{ download_timeout }}" - when: internet_available | bool + when: internet_available - name: Unarchive (unpack) it to /library/{{ dokuwiki_version }} unarchive: diff --git a/roles/0-DEPRECATED-ROLES/ejabberd/tasks/main.yml b/roles/0-DEPRECATED-ROLES/ejabberd/tasks/main.yml index c7631ec10..4aced1e51 100644 --- a/roles/0-DEPRECATED-ROLES/ejabberd/tasks/main.yml +++ b/roles/0-DEPRECATED-ROLES/ejabberd/tasks/main.yml @@ -34,7 +34,7 @@ # src: ejabberd-iiab.init # dest: /etc/init.d/ejabberd-iiab # mode: 0755 -# when: is_debuntu | bool +# when: is_debuntu #- name: Put the startup script in place - non debian # template: @@ -71,7 +71,7 @@ #name: ejabberd-iiab state: restarted enabled: yes - when: ejabberd_enabled | bool + when: ejabberd_enabled #when: ejabberd_config.changed and ejabberd_enabled #- name: Wait for ejabberd service start diff --git a/roles/0-DEPRECATED-ROLES/homepage/tasks/main.yml b/roles/0-DEPRECATED-ROLES/homepage/tasks/main.yml index d3eccd12c..9a575746f 100644 --- a/roles/0-DEPRECATED-ROLES/homepage/tasks/main.yml +++ b/roles/0-DEPRECATED-ROLES/homepage/tasks/main.yml @@ -18,4 +18,4 @@ # src: "/etc/{{ apache_conf_dir }}/iiab-homepage.conf" # path: /etc/apache2/sites-enabled/iiab-homepage.conf # state: link - # when: is_debuntu | bool + # when: is_debuntu diff --git a/roles/0-DEPRECATED-ROLES/idmgr/tasks/main.yml b/roles/0-DEPRECATED-ROLES/idmgr/tasks/main.yml index 7958b1135..241e2335a 100644 --- a/roles/0-DEPRECATED-ROLES/idmgr/tasks/main.yml +++ b/roles/0-DEPRECATED-ROLES/idmgr/tasks/main.yml @@ -42,7 +42,7 @@ with_items: - idmgr - xinetd - when: xo_services_enabled | bool + when: xo_services_enabled - name: Disable idmgr service service: name={{ item }} diff --git a/roles/0-DEPRECATED-ROLES/nodogsplash/tasks/main.yml b/roles/0-DEPRECATED-ROLES/nodogsplash/tasks/main.yml index 5fb548488..f8522daa7 100644 --- a/roles/0-DEPRECATED-ROLES/nodogsplash/tasks/main.yml +++ b/roles/0-DEPRECATED-ROLES/nodogsplash/tasks/main.yml @@ -1,3 +1,3 @@ - name: Install nodogsplash (Raspbian only) include_tasks: rpi.yml - when: is_raspbian | bool + when: is_raspbian diff --git a/roles/0-DEPRECATED-ROLES/nodogsplash/tasks/rpi.yml b/roles/0-DEPRECATED-ROLES/nodogsplash/tasks/rpi.yml index dd5c3785f..6cc1f6026 100644 --- a/roles/0-DEPRECATED-ROLES/nodogsplash/tasks/rpi.yml +++ b/roles/0-DEPRECATED-ROLES/nodogsplash/tasks/rpi.yml @@ -8,7 +8,7 @@ url: "{{ iiab_download_url }}/{{ nodogsplash_arm_deb }}" dest: "{{ downloads_dir }}/{{ nodogsplash_arm_deb }}" timeout: "{{ download_timeout }}" - when: internet_available | bool + when: internet_available #async: 300 #poll: 5 @@ -43,7 +43,7 @@ name: nodogsplash enabled: yes state: started - when: nodogsplash_enabled | bool + when: nodogsplash_enabled - name: Disable 'nodogsplash' systemd service, if not nodogsplash_enabled systemd: diff --git a/roles/0-DEPRECATED-ROLES/osm/tasks/main.yml b/roles/0-DEPRECATED-ROLES/osm/tasks/main.yml index 20a38fac5..f71f82e39 100644 --- a/roles/0-DEPRECATED-ROLES/osm/tasks/main.yml +++ b/roles/0-DEPRECATED-ROLES/osm/tasks/main.yml @@ -7,7 +7,7 @@ - libapache2-mod-wsgi - libapache2-mod-xsendfile state: present - when: is_debuntu | bool + when: is_debuntu - name: Install 6 OSM required packages (not debuntu) package: @@ -110,7 +110,7 @@ group: root mode: 0644 backup: no - when: osm_enabled | bool + when: osm_enabled - name: Create softlink osm.conf from sites-enabled to sites-available (debuntu) file: @@ -144,7 +144,7 @@ owner: root group: root state: link - when: osm_enabled | bool + when: osm_enabled - name: Create dir /library/knowledge/modules file: @@ -165,7 +165,7 @@ - { src: 'map.html', dest: "{{ osm_path }}/static/map.html" } - { src: 'l.control.geosearch.js', dest: "{{ osm_path }}/static/lib/leaflet/geosearch/l.control.geosearch.js" } - { src: "{{ osm_path }}/static/map.html", dest: "{{ osm_path }}/static/index.html" } - when: osm_enabled | bool + when: osm_enabled - name: Restart httpd service service: diff --git a/roles/0-DEPRECATED-ROLES/owncloud/tasks/main.yml b/roles/0-DEPRECATED-ROLES/owncloud/tasks/main.yml index 8726df4ae..2ab1c4606 100644 --- a/roles/0-DEPRECATED-ROLES/owncloud/tasks/main.yml +++ b/roles/0-DEPRECATED-ROLES/owncloud/tasks/main.yml @@ -4,7 +4,7 @@ - name: add a repo def for ubuntu template: dest=/etc/apt/sources.list.d/ src=owncloud.list - when: is_ubuntu | bool + when: is_ubuntu - name: See if the owncloud startup page exists stat: path={{ owncloud_prefix }}/owncloud/index.php @@ -40,7 +40,7 @@ - name: Get the owncloud software get_url: url={{ iiab_download_url }}/{{ owncloud_src_file }} dest={{ downloads_dir }}/{{ owncloud_src_file }} - when: internet_available | bool + when: internet_available async: 300 poll: 5 @@ -54,7 +54,7 @@ - name: Copy it to permanent location /opt unarchive: src={{ downloads_dir }}/{{ owncloud_src_file }} dest={{ owncloud_prefix }} - when: is_F18 | bool + when: is_F18 - name: in Centos, the following config dir is symlink to /etc/owncloud file: path=/etc/owncloud @@ -103,7 +103,7 @@ # Enable owncloud by copying template to httpd config - include_tasks: owncloud_enabled.yml - when: owncloud_enabled | bool + when: owncloud_enabled - name: Add 'owncloud' variable values to {{ iiab_ini_file }} ini_file: diff --git a/roles/0-DEPRECATED-ROLES/pathagar/tasks/main.yml b/roles/0-DEPRECATED-ROLES/pathagar/tasks/main.yml index 302edb5e0..4b520910b 100644 --- a/roles/0-DEPRECATED-ROLES/pathagar/tasks/main.yml +++ b/roles/0-DEPRECATED-ROLES/pathagar/tasks/main.yml @@ -29,7 +29,7 @@ - libapache2-mod-wsgi - libxml2-dev - libxslt-dev - when: is_debuntu | bool + when: is_debuntu - name: "Install Pathagar prerequisites: mod_wsgi, libxml2-devel, libxslt-devel (not debuntu)" package: @@ -78,7 +78,7 @@ - django-tagging==0.3.1 - django-sendfile==0.3.6 - lxml==3.4.4 - when: internet_available | bool + when: internet_available - name: Install Pathagar requirements in a virtualenv pip: diff --git a/roles/0-DEPRECATED-ROLES/schooltool/tasks/main.yml b/roles/0-DEPRECATED-ROLES/schooltool/tasks/main.yml index dad203f29..7d1020990 100644 --- a/roles/0-DEPRECATED-ROLES/schooltool/tasks/main.yml +++ b/roles/0-DEPRECATED-ROLES/schooltool/tasks/main.yml @@ -41,13 +41,13 @@ service: name=docker state=restarted enabled=yes - when: schooltool_enabled | bool + when: schooltool_enabled - name: Enable schooltool service: name=schooltool state=started enabled=yes - when: schooltool_enabled | bool + when: schooltool_enabled - name: Disable schooltool service: name=schooltool diff --git a/roles/0-DEPRECATED-ROLES/sugar-stats/tasks/main.yml b/roles/0-DEPRECATED-ROLES/sugar-stats/tasks/main.yml index bb29c4298..c1cee4459 100644 --- a/roles/0-DEPRECATED-ROLES/sugar-stats/tasks/main.yml +++ b/roles/0-DEPRECATED-ROLES/sugar-stats/tasks/main.yml @@ -29,7 +29,7 @@ - name: Enable sugar-stats service service: name=sugar-stats-server enabled=yes - when: sugar_stats_enabled | bool + when: sugar_stats_enabled - name: Disable sugar-stats service service: name=sugar-stats-server diff --git a/roles/0-DEPRECATED-ROLES/sugar-stats/tasks/statistics-consolidation.yml b/roles/0-DEPRECATED-ROLES/sugar-stats/tasks/statistics-consolidation.yml index 7ec8a9359..13a04cbfb 100644 --- a/roles/0-DEPRECATED-ROLES/sugar-stats/tasks/statistics-consolidation.yml +++ b/roles/0-DEPRECATED-ROLES/sugar-stats/tasks/statistics-consolidation.yml @@ -4,7 +4,7 @@ - name: Install statistics-consolidation with pip pip: name=stats-consolidation version=2.1.2 - when: internet_available | bool + when: internet_available - name: Install required libraries package: name={{ item }} diff --git a/roles/0-DEPRECATED-ROLES/teamviewer/tasks/install.yml b/roles/0-DEPRECATED-ROLES/teamviewer/tasks/install.yml index 082faf382..44d674b11 100644 --- a/roles/0-DEPRECATED-ROLES/teamviewer/tasks/install.yml +++ b/roles/0-DEPRECATED-ROLES/teamviewer/tasks/install.yml @@ -20,7 +20,7 @@ url: "{{ teamviewer_url }}/{{ teamviewer_rpm_file }}" dest: "{{ yum_packages_dir }}/{{ teamviewer_rpm_file }}" timeout: "{{ download_timeout }}" - when: internet_available | bool + when: internet_available # F22 has issues with yum localinstall exclude for now - name: Do the install of TeamViewer, pulling in any required dependencies diff --git a/roles/0-DEPRECATED-ROLES/teamviewer/tasks/main.yml b/roles/0-DEPRECATED-ROLES/teamviewer/tasks/main.yml index 1a6dfc9c9..5ebfa0c66 100644 --- a/roles/0-DEPRECATED-ROLES/teamviewer/tasks/main.yml +++ b/roles/0-DEPRECATED-ROLES/teamviewer/tasks/main.yml @@ -6,7 +6,7 @@ - name: Install Teamviewer if intel include_tasks: install.yml - when: teamviewer_install | bool + when: teamviewer_install - name: Add 'teamviewer' variable values to {{ iiab_ini_file }} ini_file: diff --git a/roles/0-DEPRECATED-ROLES/xovis/tasks/main.yml b/roles/0-DEPRECATED-ROLES/xovis/tasks/main.yml index aab3f668d..287858989 100644 --- a/roles/0-DEPRECATED-ROLES/xovis/tasks/main.yml +++ b/roles/0-DEPRECATED-ROLES/xovis/tasks/main.yml @@ -7,7 +7,7 @@ - python-pip - nodejs - npm - when: internet_available | bool + when: internet_available - name: Determine if xovis is already downloaded stat: path={{ downloadds_dir }}/xovis/xxx @@ -23,7 +23,7 @@ npm: name=kanso global=yes path={{ downloads_dir }} - when: internet_available | bool + when: internet_available - name: move the xovis repo into place shell: "cp -rp {{ downloads_dir }}/xovis {{ xovis_root }}" @@ -37,7 +37,7 @@ - name: Install the xovis python dependencies pip: requirements={{ xovis_root }}/process_stats/requirements.txt - when: internet_available | bool + when: internet_available - name: Update xovis repo with Chart Heading lineinfile: dest="{{ xovis_root }}/index.html" regexp='(.+)
s around - // "paragraphs" that are wrapped in non-block-level tags, such as anchors, - // phrase emphasis, and spans. The list of tags we're looking for is - // hard-coded: - var block_tags_a = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del" - var block_tags_b = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math" - - // First, look for nested blocks, e.g.: - //
tags around block-level tags.
- text = _HashHTMLBlocks(text);
- text = _FormParagraphs(text, doNotUnhash);
-
- return text;
- }
-
- function _RunSpanGamut(text) {
- //
- // These are all the transformations that occur *within* block-level
- // tags like paragraphs, headers, and list items.
- //
-
- text = pluginHooks.preSpanGamut(text);
-
- text = _DoCodeSpans(text);
- text = _EscapeSpecialCharsWithinTagAttributes(text);
- text = _EncodeBackslashEscapes(text);
-
- // Process anchor and image tags. Images must come first,
- // because ![foo][f] looks like an anchor.
- text = _DoImages(text);
- text = _DoAnchors(text);
-
- // Make links out of things like ` Just type tags
- //
-
- // Strip leading and trailing lines:
- text = text.replace(/^\n+/g, "");
- text = text.replace(/\n+$/g, "");
-
- var grafs = text.split(/\n{2,}/g);
- var grafsOut = [];
-
- var markerRe = /~K(\d+)K/;
-
- //
- // Wrap tags.
- //
- var end = grafs.length;
- for (var i = 0; i < end; i++) {
- var str = grafs[i];
-
- // if this is an HTML marker, copy it
- if (markerRe.test(str)) {
- grafsOut.push(str);
- }
- else if (/\S/.test(str)) {
- str = _RunSpanGamut(str);
- str = str.replace(/^([ \t]*)/g, " ");
- str += " s around
+ // "paragraphs" that are wrapped in non-block-level tags, such as anchors,
+ // phrase emphasis, and spans. The list of tags we're looking for is
+ // hard-coded:
+ var block_tags_a = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math|ins|del"
+ var block_tags_b = "p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|script|noscript|form|fieldset|iframe|math"
+
+ // First, look for nested blocks, e.g.:
+ // tags around block-level tags.
+ text = _HashHTMLBlocks(text);
+ text = _FormParagraphs(text, doNotUnhash);
+
+ return text;
+ }
+
+ function _RunSpanGamut(text) {
+ //
+ // These are all the transformations that occur *within* block-level
+ // tags like paragraphs, headers, and list items.
+ //
+
+ text = pluginHooks.preSpanGamut(text);
+
+ text = _DoCodeSpans(text);
+ text = _EscapeSpecialCharsWithinTagAttributes(text);
+ text = _EncodeBackslashEscapes(text);
+
+ // Process anchor and image tags. Images must come first,
+ // because ![foo][f] looks like an anchor.
+ text = _DoImages(text);
+ text = _DoAnchors(text);
+
+ // Make links out of things like ` Just type tags
+ //
+
+ // Strip leading and trailing lines:
+ text = text.replace(/^\n+/g, "");
+ text = text.replace(/\n+$/g, "");
+
+ var grafs = text.split(/\n{2,}/g);
+ var grafsOut = [];
+
+ var markerRe = /~K(\d+)K/;
+
+ //
+ // Wrap tags.
+ //
+ var end = grafs.length;
+ for (var i = 0; i < end; i++) {
+ var str = grafs[i];
+
+ // if this is an HTML marker, copy it
+ if (markerRe.test(str)) {
+ grafsOut.push(str);
+ }
+ else if (/\S/.test(str)) {
+ str = _RunSpanGamut(str);
+ str = str.replace(/^([ \t]*)/g, " ");
+ str += "
\n");
-
- text = pluginHooks.postSpanGamut(text);
-
- return text;
- }
-
- function _EscapeSpecialCharsWithinTagAttributes(text) {
- //
- // Within tags -- meaning between < and > -- encode [\ ` * _] so they
- // don't conflict with their use in Markdown for code, italics and strong.
- //
-
- // Build a regex to find HTML tags and comments. See Friedl's
- // "Mastering Regular Expressions", 2nd Ed., pp. 200-201.
-
- // SE: changed the comment part of the regex
-
- var regex = /(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|-]|-[^>])(?:[^-]|-[^-])*)--)>)/gi;
-
- text = text.replace(regex, function (wholeMatch) {
- var tag = wholeMatch.replace(/(.)<\/?code>(?=.)/g, "$1`");
- tag = escapeCharacters(tag, wholeMatch.charAt(1) == "!" ? "\\`*_/" : "\\`*_"); // also escape slashes in comments to prevent autolinking there -- http://meta.stackexchange.com/questions/95987
- return tag;
- });
-
- return text;
- }
-
- function _DoAnchors(text) {
-
- if (text.indexOf("[") === -1)
- return text;
-
- //
- // Turn Markdown link shortcuts into XHTML tags.
- //
- //
- // First, handle reference-style links: [link text] [id]
- //
-
- /*
- text = text.replace(/
- ( // wrap whole match in $1
- \[
- (
- (?:
- \[[^\]]*\] // allow brackets nested one level
- |
- [^\[] // or anything else
- )*
- )
- \]
-
- [ ]? // one optional space
- (?:\n[ ]*)? // one optional newline followed by spaces
-
- \[
- (.*?) // id = $3
- \]
- )
- ()()()() // pad remaining backreferences
- /g, writeAnchorTag);
- */
- text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, writeAnchorTag);
-
- //
- // Next, inline-style links: [link text](url "optional title")
- //
-
- /*
- text = text.replace(/
- ( // wrap whole match in $1
- \[
- (
- (?:
- \[[^\]]*\] // allow brackets nested one level
- |
- [^\[\]] // or anything else
- )*
- )
- \]
- \( // literal paren
- [ \t]*
- () // no id, so leave $3 empty
- ( // href = $4
- (?:
- \([^)]*\) // allow one level of (correctly nested) parens (think MSDN)
- |
- [^()\s]
- )*?
- )>?
- [ \t]*
- ( // $5
- (['"]) // quote char = $6
- (.*?) // Title = $7
- \6 // matching quote
- [ \t]* // ignore any spaces/tabs between closing quote and )
- )? // title is optional
- \)
- )
- /g, writeAnchorTag);
- */
-
- text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()((?:\([^)]*\)|[^()\s])*?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, writeAnchorTag);
-
- //
- // Last, handle reference-style shortcuts: [link text]
- // These must come last in case you've also got [link test][1]
- // or [link test](/foo)
- //
-
- /*
- text = text.replace(/
- ( // wrap whole match in $1
- \[
- ([^\[\]]+) // link text = $2; can't contain '[' or ']'
- \]
- )
- ()()()()() // pad rest of backreferences
- /g, writeAnchorTag);
- */
- text = text.replace(/(\[([^\[\]]+)\])()()()()()/g, writeAnchorTag);
-
- return text;
- }
-
- function writeAnchorTag(wholeMatch, m1, m2, m3, m4, m5, m6, m7) {
- if (m7 == undefined) m7 = "";
- var whole_match = m1;
- var link_text = m2.replace(/:\/\//g, "~P"); // to prevent auto-linking withing the link. will be converted back after the auto-linker runs
- var link_id = m3.toLowerCase();
- var url = m4;
- var title = m7;
-
- if (url == "") {
- if (link_id == "") {
- // lower-case and turn embedded newlines into spaces
- link_id = link_text.toLowerCase().replace(/ ?\n/g, " ");
- }
- url = "#" + link_id;
-
- if (g_urls.get(link_id) != undefined) {
- url = g_urls.get(link_id);
- if (g_titles.get(link_id) != undefined) {
- title = g_titles.get(link_id);
- }
- }
- else {
- if (whole_match.search(/\(\s*\)$/m) > -1) {
- // Special case for explicit empty url
- url = "";
- } else {
- return whole_match;
- }
- }
- }
- url = attributeSafeUrl(url);
-
- var result = "" + link_text + "";
-
- return result;
- }
-
- function _DoImages(text) {
-
- if (text.indexOf("![") === -1)
- return text;
-
- //
- // Turn Markdown image shortcuts into tags.
- //
-
- //
- // First, handle reference-style labeled images: ![alt text][id]
- //
-
- /*
- text = text.replace(/
- ( // wrap whole match in $1
- !\[
- (.*?) // alt text = $2
- \]
-
- [ ]? // one optional space
- (?:\n[ ]*)? // one optional newline followed by spaces
-
- \[
- (.*?) // id = $3
- \]
- )
- ()()()() // pad rest of backreferences
- /g, writeImageTag);
- */
- text = text.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, writeImageTag);
-
- //
- // Next, handle inline images: 
- // Don't forget: encode * and _
-
- /*
- text = text.replace(/
- ( // wrap whole match in $1
- !\[
- (.*?) // alt text = $2
- \]
- \s? // One optional whitespace character
- \( // literal paren
- [ \t]*
- () // no id, so leave $3 empty
- (\S+?)>? // src url = $4
- [ \t]*
- ( // $5
- (['"]) // quote char = $6
- (.*?) // title = $7
- \6 // matching quote
- [ \t]*
- )? // title is optional
- \)
- )
- /g, writeImageTag);
- */
- text = text.replace(/(!\[(.*?)\]\s?\([ \t]*()(\S+?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, writeImageTag);
-
- return text;
- }
-
- function attributeEncode(text) {
- // unconditionally replace angle brackets here -- what ends up in an attribute (e.g. alt or title)
- // never makes sense to have verbatim HTML in it (and the sanitizer would totally break it)
- return text.replace(/>/g, ">").replace(/";
-
- return result;
- }
-
- function _DoHeaders(text) {
-
- // Setext-style headers:
- // Header 1
- // ========
- //
- // Header 2
- // --------
- //
- text = text.replace(/^(.+)[ \t]*\n=+[ \t]*\n+/gm,
- function (wholeMatch, m1) { return "
" + _RunSpanGamut(m1) + "
\n\n"; }
- );
-
- text = text.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm,
- function (matchFound, m1) { return "" + _RunSpanGamut(m1) + "
\n\n"; }
- );
-
- // atx-style headers:
- // # Header 1
- // ## Header 2
- // ## Header 2 with closing hashes ##
- // ...
- // ###### Header 6
- //
-
- /*
- text = text.replace(/
- ^(\#{1,6}) // $1 = string of #'s
- [ \t]*
- (.+?) // $2 = Header text
- [ \t]*
- \#* // optional closing #'s (not counted)
- \n+
- /gm, function() {...});
- */
-
- text = text.replace(/^(\#{1,6})[ \t]*(.+?)[ \t]*\#*\n+/gm,
- function (wholeMatch, m1, m2) {
- var h_level = m1.length;
- return "` blocks.
- //
-
- /*
- text = text.replace(/
- (?:\n\n|^)
- ( // $1 = the code block -- one or more lines, starting with a space/tab
- (?:
- (?:[ ]{4}|\t) // Lines must start with a tab or a tab-width of spaces - attacklab: g_tab_width
- .*\n+
- )+
- )
- (\n*[ ]{0,3}[^ \t\n]|(?=~0)) // attacklab: g_tab_width
- /g ,function(){...});
- */
-
- // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
- text += "~0";
-
- text = text.replace(/(?:\n\n|^\n?)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g,
- function (wholeMatch, m1, m2) {
- var codeblock = m1;
- var nextChar = m2;
-
- codeblock = _EncodeCode(_Outdent(codeblock));
- codeblock = _Detab(codeblock);
- codeblock = codeblock.replace(/^\n+/g, ""); // trim leading newlines
- codeblock = codeblock.replace(/\n+$/g, ""); // trim trailing whitespace
-
- codeblock = "
";
-
- return "\n\n" + codeblock + "\n\n" + nextChar;
- }
- );
-
- // attacklab: strip sentinel
- text = text.replace(/~0/, "");
-
- return text;
- }
-
- function _DoCodeSpans(text) {
- //
- // * Backtick quotes are used for " + codeblock + "\n
spans.
- //
- // * You can use multiple backticks as the delimiters if you want to
- // include literal backticks in the code span. So, this input:
- //
- // Just type ``foo `bar` baz`` at the prompt.
- //
- // Will translate to:
- //
- //
foo `bar` baz
at the prompt.`bar`
...
- //
-
- /*
- text = text.replace(/
- (^|[^\\`]) // Character before opening ` can't be a backslash or backtick
- (`+) // $2 = Opening run of `
- (?!`) // and no more backticks -- match the full run
- ( // $3 = The code block
- [^\r]*?
- [^`] // attacklab: work around lack of lookbehind
- )
- \2 // Matching closer
- (?!`)
- /gm, function(){...});
- */
-
- text = text.replace(/(^|[^\\`])(`+)(?!`)([^\r]*?[^`])\2(?!`)/gm,
- function (wholeMatch, m1, m2, m3, m4) {
- var c = m3;
- c = c.replace(/^([ \t]*)/g, ""); // leading whitespace
- c = c.replace(/[ \t]*$/g, ""); // trailing whitespace
- c = _EncodeCode(c);
- 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.
- return m1 + "" + c + "
";
- }
- );
-
- return text;
- }
-
- function _EncodeCode(text) {
- //
- // Encode/escape certain characters inside Markdown code runs.
- // The point is that in code, these characters are literals,
- // and lose their special Markdown meanings.
- //
- // Encode all ampersands; HTML entities are not
- // entities within a Markdown code span.
- text = text.replace(/&/g, "&");
-
- // Do the angle bracket song and dance:
- text = text.replace(//g, ">");
-
- // Now, escape characters that are magic in Markdown:
- text = escapeCharacters(text, "\*_{}[]\\", false);
-
- // jj the line above breaks this:
- //---
-
- //* Item
-
- // 1. Subitem
-
- // special char: *
- //---
-
- return text;
- }
-
- function _DoItalicsAndBoldStrict(text) {
-
- if (text.indexOf("*") === -1 && text.indexOf("_") === - 1)
- return text;
-
- text = asciify(text);
-
- // must go first:
-
- // (^|[\W_]) Start with a non-letter or beginning of string. Store in \1.
- // (?:(?!\1)|(?=^)) Either the next character is *not* the same as the previous,
- // or we started at the end of the string (in which case the previous
- // group had zero width, so we're still there). Because the next
- // character is the marker, this means that if there are e.g. multiple
- // underscores in a row, we can only match the left-most ones (which
- // prevents foo___bar__ from getting bolded)
- // (\*|_) The marker character itself, asterisk or underscore. Store in \2.
- // \2 The marker again, since bold needs two.
- // (?=\S) The first bolded character cannot be a space.
- // ([^\r]*?\S) The actual bolded string. At least one character, and it cannot *end*
- // with a space either. Note that like in many other places, [^\r] is
- // just a workaround for JS' lack of single-line regexes; it's equivalent
- // to a . in an /s regex, because the string cannot contain any \r (they
- // are removed in the normalizing step).
- // \2\2 The marker character, twice -- end of bold.
- // (?!\2) Not followed by another marker character (ensuring that we match the
- // rightmost two in a longer row)...
- // (?=[\W_]|$) ...but by any other non-word character or the end of string.
- text = text.replace(/(^|[\W_])(?:(?!\1)|(?=^))(\*|_)\2(?=\S)([^\r]*?\S)\2\2(?!\2)(?=[\W_]|$)/g,
- "$1$3");
-
- // This is almost identical to the regex, except 1) there's obviously just one marker
- // character, and 2) the italicized string cannot contain the marker character.
- text = text.replace(/(^|[\W_])(?:(?!\1)|(?=^))(\*|_)(?=\S)((?:(?!\2)[^\r])*?\S)\2(?!\2)(?=[\W_]|$)/g,
- "$1$3");
-
- return deasciify(text);
- }
-
- function _DoItalicsAndBold_AllowIntrawordWithAsterisk(text) {
-
- if (text.indexOf("*") === -1 && text.indexOf("_") === - 1)
- return text;
-
- text = asciify(text);
-
- // must go first:
- // (?=[^\r][*_]|[*_]) Optimization only, to find potentially relevant text portions faster. Minimally slower in Chrome, but much faster in IE.
- // ( Store in \1. This is the last character before the delimiter
- // ^ Either we're at the start of the string (i.e. there is no last character)...
- // | ... or we allow one of the following:
- // (?= (lookahead; we're not capturing this, just listing legal possibilities)
- // \W__ If the delimiter is __, then this last character must be non-word non-underscore (extra-word emphasis only)
- // |
- // (?!\*)[\W_]\*\* If the delimiter is **, then this last character can be non-word non-asterisk (extra-word emphasis)...
- // |
- // \w\*\*\w ...or it can be word/underscore, but only if the first bolded character is such a character as well (intra-word emphasis)
- // )
- // [^\r] actually capture the character (can't use `.` since it could be \n)
- // )
- // (\*\*|__) Store in \2: the actual delimiter
- // (?!\2) not followed by the delimiter again (at most one more asterisk/underscore is allowed)
- // (?=\S) the first bolded character can't be a space
- // ( Store in \3: the bolded string
- //
- // (?:| Look at all bolded characters except for the last one. Either that's empty, meaning only a single character was bolded...
- // [^\r]*? ... otherwise take arbitrary characters, minimally matching; that's all bolded characters except for the last *two*
- // (?!\2) the last two characters cannot be the delimiter itself (because that would mean four underscores/asterisks in a row)
- // [^\r] capture the next-to-last bolded character
- // )
- // (?= lookahead at the very last bolded char and what comes after
- // \S_ for underscore-bolding, it can be any non-space
- // |
- // \w for asterisk-bolding (otherwise the previous alternative would've matched, since \w implies \S), either the last char is word/underscore...
- // |
- // \S\*\*(?:[\W_]|$) ... or it's any other non-space, but in that case the character *after* the delimiter may not be a word character
- // )
- // . actually capture the last character (can use `.` this time because the lookahead ensures \S in all cases)
- // )
- // (?= lookahead; list the legal possibilities for the closing delimiter and its following character
- // __(?:\W|$) for underscore-bolding, the following character (if any) must be non-word non-underscore
- // |
- // \*\*(?:[^*]|$) for asterisk-bolding, any non-asterisk is allowed (note we already ensured above that it's not a word character if the last bolded character wasn't one)
- // )
- // \2 actually capture the closing delimiter (and make sure that it matches the opening one)
-
- text = text.replace(/(?=[^\r][*_]|[*_])(^|(?=\W__|(?!\*)[\W_]\*\*|\w\*\*\w)[^\r])(\*\*|__)(?!\2)(?=\S)((?:|[^\r]*?(?!\2)[^\r])(?=\S_|\w|\S\*\*(?:[\W_]|$)).)(?=__(?:\W|$)|\*\*(?:[^*]|$))\2/g,
- "$1$3");
-
- // now :
- // (?=[^\r][*_]|[*_]) Optimization, see above.
- // ( Store in \1. This is the last character before the delimiter
- // ^ Either we're at the start of the string (i.e. there is no last character)...
- // | ... or we allow one of the following:
- // (?= (lookahead; we're not capturing this, just listing legal possibilities)
- // \W_ If the delimiter is _, then this last character must be non-word non-underscore (extra-word emphasis only)
- // |
- // (?!\*) otherwise, we list two possiblities for * as the delimiter; in either case, the last characters cannot be an asterisk itself
- // (?:
- // [\W_]\* this last character can be non-word (extra-word emphasis)...
- // |
- // \D\*(?=\w)\D ...or it can be word (otherwise the first alternative would've matched), but only if
- // a) the first italicized character is such a character as well (intra-word emphasis), and
- // b) neither character on either side of the asterisk is a digit
- // )
- // )
- // [^\r] actually capture the character (can't use `.` since it could be \n)
- // )
- // (\*|_) Store in \2: the actual delimiter
- // (?!\2\2\2) not followed by more than two more instances of the delimiter
- // (?=\S) the first italicized character can't be a space
- // ( Store in \3: the italicized string
- // (?:(?!\2)[^\r])*? arbitrary characters except for the delimiter itself, minimally matching
- // (?= lookahead at the very last italicized char and what comes after
- // [^\s_]_ for underscore-italicizing, it can be any non-space non-underscore
- // |
- // (?=\w)\D\*\D for asterisk-italicizing, either the last char is word/underscore *and* neither character on either side of the asterisk is a digit...
- // |
- // [^\s*]\*(?:[\W_]|$) ... or that last char is any other non-space non-asterisk, but then the character after the delimiter (if any) must be non-word
- // )
- // . actually capture the last character (can use `.` this time because the lookahead ensures \S in all cases)
- // )
- // (?= lookahead; list the legal possibilities for the closing delimiter and its following character
- // _(?:\W|$) for underscore-italicizing, the following character (if any) must be non-word non-underscore
- // |
- // \*(?:[^*]|$) for asterisk-italicizing, any non-asterisk is allowed; all other restrictions have already been ensured in the previous lookahead
- // )
- // \2 actually capture the closing delimiter (and make sure that it matches the opening one)
-
- text = text.replace(/(?=[^\r][*_]|[*_])(^|(?=\W_|(?!\*)(?:[\W_]\*|\D\*(?=\w)\D))[^\r])(\*|_)(?!\2\2\2)(?=\S)((?:(?!\2)[^\r])*?(?=[^\s_]_|(?=\w)\D\*\D|[^\s*]\*(?:[\W_]|$)).)(?=_(?:\W|$)|\*(?:[^*]|$))\2/g,
- "$1$3");
-
- return deasciify(text);
- }
-
-
- function _DoBlockQuotes(text) {
-
- /*
- text = text.replace(/
- ( // Wrap whole match in $1
- (
- ^[ \t]*>[ \t]? // '>' at the start of a line
- .+\n // rest of the first line
- (.+\n)* // subsequent consecutive lines
- \n* // blanks
- )+
- )
- /gm, function(){...});
- */
-
- text = text.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm,
- function (wholeMatch, m1) {
- var bq = m1;
-
- // attacklab: hack around Konqueror 3.5.4 bug:
- // "----------bug".replace(/^-/g,"") == "bug"
-
- bq = bq.replace(/^[ \t]*>[ \t]?/gm, "~0"); // trim one level of quoting
-
- // attacklab: clean up hack
- bq = bq.replace(/~0/g, "");
-
- bq = bq.replace(/^[ \t]+$/gm, ""); // trim whitespace-only lines
- bq = _RunBlockGamut(bq); // recurse
-
- bq = bq.replace(/(^|\n)/g, "$1 ");
- // These leading spaces screw with content, so we need to fix that:
- bq = bq.replace(
- /(\s*
[^\r]+?<\/pre>)/gm,
- function (wholeMatch, m1) {
- var pre = m1;
- // attacklab: hack around Konqueror 3.5.4 bug:
- pre = pre.replace(/^ /mg, "~0");
- pre = pre.replace(/~0/g, "");
- return pre;
- });
-
- return hashBlock("
\n" + bq + "\n
");
- }
- );
- return text;
- }
-
- function _FormParagraphs(text, doNotUnhash) {
- //
- // Params:
- // $text - string to process with html tags get encoded.
+ //
+
+ // This will only happen if makeHtml on the same converter instance is called from a plugin hook.
+ // Don't do that.
+ if (g_urls)
+ throw new Error("Recursive call to converter.makeHtml");
+
+ // Create the private state objects.
+ g_urls = new SaveHash();
+ g_titles = new SaveHash();
+ g_html_blocks = [];
+ g_list_level = 0;
+
+ text = pluginHooks.preConversion(text);
+
+ // attacklab: Replace ~ with ~T
+ // This lets us use tilde as an escape char to avoid md5 hashes
+ // The choice of character is arbitray; anything that isn't
+ // magic in Markdown will work.
+ text = text.replace(/~/g, "~T");
+
+ // attacklab: Replace $ with ~D
+ // RegExp interprets $ as a special character
+ // when it's in a replacement string
+ text = text.replace(/\$/g, "~D");
+
+ // Standardize line endings
+ text = text.replace(/\r\n/g, "\n"); // DOS to Unix
+ text = text.replace(/\r/g, "\n"); // Mac to Unix
+
+ // Make sure text begins and ends with a couple of newlines:
+ text = "\n\n" + text + "\n\n";
+
+ // Convert all tabs to spaces.
+ text = _Detab(text);
+
+ // Strip any lines consisting only of spaces and tabs.
+ // This makes subsequent regexen easier to write, because we can
+ // match consecutive blank lines with /\n+/ instead of something
+ // contorted like /[ \t]*\n+/ .
+ text = text.replace(/^[ \t]+$/mg, "");
+
+ text = pluginHooks.postNormalization(text);
+
+ // Turn block-level HTML blocks into hash entries
+ text = _HashHTMLBlocks(text);
+
+ // Strip link definitions, store in hashes.
+ text = _StripLinkDefinitions(text);
+
+ text = _RunBlockGamut(text);
+
+ text = _UnescapeSpecialChars(text);
+
+ // attacklab: Restore dollar signs
+ text = text.replace(/~D/g, "$$");
+
+ // attacklab: Restore tildes
+ text = text.replace(/~T/g, "~");
+
+ text = pluginHooks.postConversion(text);
+
+ g_html_blocks = g_titles = g_urls = null;
+
+ return text;
+ };
+
+ function _StripLinkDefinitions(text) {
+ //
+ // Strips link definitions from text, stores the URLs and titles in
+ // hash references.
+ //
+
+ // Link defs are in the form: ^[id]: url "optional title"
+
+ /*
+ text = text.replace(/
+ ^[ ]{0,3}\[([^\[\]]+)\]: // id = $1 attacklab: g_tab_width - 1
+ [ \t]*
+ \n? // maybe *one* newline
+ [ \t]*
+ (\S+?)>? // url = $2
+ (?=\s|$) // lookahead for whitespace instead of the lookbehind removed below
+ [ \t]*
+ \n? // maybe one newline
+ [ \t]*
+ ( // (potential) title = $3
+ (\n*) // any lines skipped = $4 attacklab: lookbehind removed
+ [ \t]+
+ ["(]
+ (.+?) // title = $5
+ [")]
+ [ \t]*
+ )? // title is optional
+ (?:\n+|$)
+ /gm, function(){...});
+ */
+
+ text = text.replace(/^[ ]{0,3}\[([^\[\]]+)\]:[ \t]*\n?[ \t]*(\S+?)>?(?=\s|$)[ \t]*\n?[ \t]*((\n*)["(](.+?)[")][ \t]*)?(?:\n+)/gm,
+ function (wholeMatch, m1, m2, m3, m4, m5) {
+ m1 = m1.toLowerCase();
+ g_urls.set(m1, _EncodeAmpsAndAngles(m2)); // Link IDs are case-insensitive
+ if (m4) {
+ // Oops, found blank lines, so it's not a title.
+ // Put back the parenthetical statement we stole.
+ return m3;
+ } else if (m5) {
+ g_titles.set(m1, m5.replace(/"/g, """));
+ }
+
+ // Completely remove the definition from the text
+ return "";
+ }
+ );
+
+ return text;
+ }
+
+ function _HashHTMLBlocks(text) {
+
+ // Hashify HTML blocks:
+ // We only want to do this for block-level HTML tags, such as headers,
+ // lists, and tables. That's because we still want to wrap
. It was easier to make a special case than
+ // to make the other regex more complicated.
+
+ /*
+ text = text.replace(/
+ \n // Starting after a blank line
+ [ ]{0,3}
+ ( // save in $1
+ (<(hr) // start tag = $2
+ \b // word break
+ ([^<>])*?
+ \/?>) // the matching end tag
+ [ \t]*
+ (?=\n{2,}) // followed by a blank line
+ )
+ /g,hashMatch);
+ */
+ text = text.replace(/\n[ ]{0,3}((<(hr)\b([^<>])*?\/?>)[ \t]*(?=\n{2,}))/g, hashMatch);
+
+ // Special case for standalone HTML comments:
+
+ /*
+ text = text.replace(/
+ \n\n // Starting after a blank line
+ [ ]{0,3} // attacklab: g_tab_width - 1
+ ( // save in $1
+ -]|-[^>])(?:[^-]|-[^-])*)--) // see http://www.w3.org/TR/html-markup/syntax.html#comments and http://meta.stackexchange.com/q/95256
+ >
+ [ \t]*
+ (?=\n{2,}) // followed by a blank line
+ )
+ /g,hashMatch);
+ */
+ text = text.replace(/\n\n[ ]{0,3}(-]|-[^>])(?:[^-]|-[^-])*)--)>[ \t]*(?=\n{2,}))/g, hashMatch);
+
+ // PHP and ASP-style processor instructions (...?> and <%...%>)
+
+ /*
+ text = text.replace(/
+ (?:
+ \n\n // Starting after a blank line
+ )
+ ( // save in $1
+ [ ]{0,3} // attacklab: g_tab_width - 1
+ (?:
+ <([?%]) // $2
+ [^\r]*?
+ \2>
+ )
+ [ \t]*
+ (?=\n{2,}) // followed by a blank line
+ )
+ /g,hashMatch);
+ */
+ text = text.replace(/(?:\n\n)([ ]{0,3}(?:<([?%])[^\r]*?\2>)[ \t]*(?=\n{2,}))/g, hashMatch);
+
+ return text;
+ }
+
+ function hashBlock(text) {
+ text = text.replace(/(^\n+|\n+$)/g, "");
+ // Replace the element text with a marker ("~KxK" where x is its key)
+ return "\n\n~K" + (g_html_blocks.push(text) - 1) + "K\n\n";
+ }
+
+ function hashMatch(wholeMatch, m1) {
+ return hashBlock(m1);
+ }
+
+ var blockGamutHookCallback = function (t) { return _RunBlockGamut(t); }
+
+ function _RunBlockGamut(text, doNotUnhash) {
+ //
+ // These are all the transformations that form block-level
+ // tags like paragraphs, headers, and list items.
+ //
+
+ text = pluginHooks.preBlockGamut(text, blockGamutHookCallback);
+
+ text = _DoHeaders(text);
+
+ // Do Horizontal Rules:
+ var replacement = "
\n";
+ text = text.replace(/^[ ]{0,2}([ ]?\*[ ]?){3,}[ \t]*$/gm, replacement);
+ text = text.replace(/^[ ]{0,2}([ ]?-[ ]?){3,}[ \t]*$/gm, replacement);
+ text = text.replace(/^[ ]{0,2}([ ]?_[ ]?){3,}[ \t]*$/gm, replacement);
+
+ text = _DoLists(text);
+ text = _DoCodeBlocks(text);
+ text = _DoBlockQuotes(text);
+
+ text = pluginHooks.postBlockGamut(text, blockGamutHookCallback);
+
+ // We already ran _HashHTMLBlocks() before, in Markdown(), but that
+ // was to escape raw HTML in the original Markdown source. This time,
+ // we're escaping the markup we've just created, so that we don't wrap
+ //
\n");
+
+ text = pluginHooks.postSpanGamut(text);
+
+ return text;
+ }
+
+ function _EscapeSpecialCharsWithinTagAttributes(text) {
+ //
+ // Within tags -- meaning between < and > -- encode [\ ` * _] so they
+ // don't conflict with their use in Markdown for code, italics and strong.
+ //
+
+ // Build a regex to find HTML tags and comments. See Friedl's
+ // "Mastering Regular Expressions", 2nd Ed., pp. 200-201.
+
+ // SE: changed the comment part of the regex
+
+ var regex = /(<[a-z\/!$]("[^"]*"|'[^']*'|[^'">])*>|-]|-[^>])(?:[^-]|-[^-])*)--)>)/gi;
+
+ text = text.replace(regex, function (wholeMatch) {
+ var tag = wholeMatch.replace(/(.)<\/?code>(?=.)/g, "$1`");
+ tag = escapeCharacters(tag, wholeMatch.charAt(1) == "!" ? "\\`*_/" : "\\`*_"); // also escape slashes in comments to prevent autolinking there -- http://meta.stackexchange.com/questions/95987
+ return tag;
+ });
+
+ return text;
+ }
+
+ function _DoAnchors(text) {
+
+ if (text.indexOf("[") === -1)
+ return text;
+
+ //
+ // Turn Markdown link shortcuts into XHTML tags.
+ //
+ //
+ // First, handle reference-style links: [link text] [id]
+ //
+
+ /*
+ text = text.replace(/
+ ( // wrap whole match in $1
+ \[
+ (
+ (?:
+ \[[^\]]*\] // allow brackets nested one level
+ |
+ [^\[] // or anything else
+ )*
+ )
+ \]
+
+ [ ]? // one optional space
+ (?:\n[ ]*)? // one optional newline followed by spaces
+
+ \[
+ (.*?) // id = $3
+ \]
+ )
+ ()()()() // pad remaining backreferences
+ /g, writeAnchorTag);
+ */
+ text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, writeAnchorTag);
+
+ //
+ // Next, inline-style links: [link text](url "optional title")
+ //
+
+ /*
+ text = text.replace(/
+ ( // wrap whole match in $1
+ \[
+ (
+ (?:
+ \[[^\]]*\] // allow brackets nested one level
+ |
+ [^\[\]] // or anything else
+ )*
+ )
+ \]
+ \( // literal paren
+ [ \t]*
+ () // no id, so leave $3 empty
+ ( // href = $4
+ (?:
+ \([^)]*\) // allow one level of (correctly nested) parens (think MSDN)
+ |
+ [^()\s]
+ )*?
+ )>?
+ [ \t]*
+ ( // $5
+ (['"]) // quote char = $6
+ (.*?) // Title = $7
+ \6 // matching quote
+ [ \t]* // ignore any spaces/tabs between closing quote and )
+ )? // title is optional
+ \)
+ )
+ /g, writeAnchorTag);
+ */
+
+ text = text.replace(/(\[((?:\[[^\]]*\]|[^\[\]])*)\]\([ \t]*()((?:\([^)]*\)|[^()\s])*?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, writeAnchorTag);
+
+ //
+ // Last, handle reference-style shortcuts: [link text]
+ // These must come last in case you've also got [link test][1]
+ // or [link test](/foo)
+ //
+
+ /*
+ text = text.replace(/
+ ( // wrap whole match in $1
+ \[
+ ([^\[\]]+) // link text = $2; can't contain '[' or ']'
+ \]
+ )
+ ()()()()() // pad rest of backreferences
+ /g, writeAnchorTag);
+ */
+ text = text.replace(/(\[([^\[\]]+)\])()()()()()/g, writeAnchorTag);
+
+ return text;
+ }
+
+ function writeAnchorTag(wholeMatch, m1, m2, m3, m4, m5, m6, m7) {
+ if (m7 == undefined) m7 = "";
+ var whole_match = m1;
+ var link_text = m2.replace(/:\/\//g, "~P"); // to prevent auto-linking withing the link. will be converted back after the auto-linker runs
+ var link_id = m3.toLowerCase();
+ var url = m4;
+ var title = m7;
+
+ if (url == "") {
+ if (link_id == "") {
+ // lower-case and turn embedded newlines into spaces
+ link_id = link_text.toLowerCase().replace(/ ?\n/g, " ");
+ }
+ url = "#" + link_id;
+
+ if (g_urls.get(link_id) != undefined) {
+ url = g_urls.get(link_id);
+ if (g_titles.get(link_id) != undefined) {
+ title = g_titles.get(link_id);
+ }
+ }
+ else {
+ if (whole_match.search(/\(\s*\)$/m) > -1) {
+ // Special case for explicit empty url
+ url = "";
+ } else {
+ return whole_match;
+ }
+ }
+ }
+ url = attributeSafeUrl(url);
+
+ var result = "" + link_text + "";
+
+ return result;
+ }
+
+ function _DoImages(text) {
+
+ if (text.indexOf("![") === -1)
+ return text;
+
+ //
+ // Turn Markdown image shortcuts into tags.
+ //
+
+ //
+ // First, handle reference-style labeled images: ![alt text][id]
+ //
+
+ /*
+ text = text.replace(/
+ ( // wrap whole match in $1
+ !\[
+ (.*?) // alt text = $2
+ \]
+
+ [ ]? // one optional space
+ (?:\n[ ]*)? // one optional newline followed by spaces
+
+ \[
+ (.*?) // id = $3
+ \]
+ )
+ ()()()() // pad rest of backreferences
+ /g, writeImageTag);
+ */
+ text = text.replace(/(!\[(.*?)\][ ]?(?:\n[ ]*)?\[(.*?)\])()()()()/g, writeImageTag);
+
+ //
+ // Next, handle inline images: 
+ // Don't forget: encode * and _
+
+ /*
+ text = text.replace(/
+ ( // wrap whole match in $1
+ !\[
+ (.*?) // alt text = $2
+ \]
+ \s? // One optional whitespace character
+ \( // literal paren
+ [ \t]*
+ () // no id, so leave $3 empty
+ (\S+?)>? // src url = $4
+ [ \t]*
+ ( // $5
+ (['"]) // quote char = $6
+ (.*?) // title = $7
+ \6 // matching quote
+ [ \t]*
+ )? // title is optional
+ \)
+ )
+ /g, writeImageTag);
+ */
+ text = text.replace(/(!\[(.*?)\]\s?\([ \t]*()(\S+?)>?[ \t]*((['"])(.*?)\6[ \t]*)?\))/g, writeImageTag);
+
+ return text;
+ }
+
+ function attributeEncode(text) {
+ // unconditionally replace angle brackets here -- what ends up in an attribute (e.g. alt or title)
+ // never makes sense to have verbatim HTML in it (and the sanitizer would totally break it)
+ return text.replace(/>/g, ">").replace(/";
+
+ return result;
+ }
+
+ function _DoHeaders(text) {
+
+ // Setext-style headers:
+ // Header 1
+ // ========
+ //
+ // Header 2
+ // --------
+ //
+ text = text.replace(/^(.+)[ \t]*\n=+[ \t]*\n+/gm,
+ function (wholeMatch, m1) { return "
" + _RunSpanGamut(m1) + "
\n\n"; }
+ );
+
+ text = text.replace(/^(.+)[ \t]*\n-+[ \t]*\n+/gm,
+ function (matchFound, m1) { return "" + _RunSpanGamut(m1) + "
\n\n"; }
+ );
+
+ // atx-style headers:
+ // # Header 1
+ // ## Header 2
+ // ## Header 2 with closing hashes ##
+ // ...
+ // ###### Header 6
+ //
+
+ /*
+ text = text.replace(/
+ ^(\#{1,6}) // $1 = string of #'s
+ [ \t]*
+ (.+?) // $2 = Header text
+ [ \t]*
+ \#* // optional closing #'s (not counted)
+ \n+
+ /gm, function() {...});
+ */
+
+ text = text.replace(/^(\#{1,6})[ \t]*(.+?)[ \t]*\#*\n+/gm,
+ function (wholeMatch, m1, m2) {
+ var h_level = m1.length;
+ return "` blocks.
+ //
+
+ /*
+ text = text.replace(/
+ (?:\n\n|^)
+ ( // $1 = the code block -- one or more lines, starting with a space/tab
+ (?:
+ (?:[ ]{4}|\t) // Lines must start with a tab or a tab-width of spaces - attacklab: g_tab_width
+ .*\n+
+ )+
+ )
+ (\n*[ ]{0,3}[^ \t\n]|(?=~0)) // attacklab: g_tab_width
+ /g ,function(){...});
+ */
+
+ // attacklab: sentinel workarounds for lack of \A and \Z, safari\khtml bug
+ text += "~0";
+
+ text = text.replace(/(?:\n\n|^\n?)((?:(?:[ ]{4}|\t).*\n+)+)(\n*[ ]{0,3}[^ \t\n]|(?=~0))/g,
+ function (wholeMatch, m1, m2) {
+ var codeblock = m1;
+ var nextChar = m2;
+
+ codeblock = _EncodeCode(_Outdent(codeblock));
+ codeblock = _Detab(codeblock);
+ codeblock = codeblock.replace(/^\n+/g, ""); // trim leading newlines
+ codeblock = codeblock.replace(/\n+$/g, ""); // trim trailing whitespace
+
+ codeblock = "
";
+
+ return "\n\n" + codeblock + "\n\n" + nextChar;
+ }
+ );
+
+ // attacklab: strip sentinel
+ text = text.replace(/~0/, "");
+
+ return text;
+ }
+
+ function _DoCodeSpans(text) {
+ //
+ // * Backtick quotes are used for " + codeblock + "\n
spans.
+ //
+ // * You can use multiple backticks as the delimiters if you want to
+ // include literal backticks in the code span. So, this input:
+ //
+ // Just type ``foo `bar` baz`` at the prompt.
+ //
+ // Will translate to:
+ //
+ //
foo `bar` baz
at the prompt.`bar`
...
+ //
+
+ /*
+ text = text.replace(/
+ (^|[^\\`]) // Character before opening ` can't be a backslash or backtick
+ (`+) // $2 = Opening run of `
+ (?!`) // and no more backticks -- match the full run
+ ( // $3 = The code block
+ [^\r]*?
+ [^`] // attacklab: work around lack of lookbehind
+ )
+ \2 // Matching closer
+ (?!`)
+ /gm, function(){...});
+ */
+
+ text = text.replace(/(^|[^\\`])(`+)(?!`)([^\r]*?[^`])\2(?!`)/gm,
+ function (wholeMatch, m1, m2, m3, m4) {
+ var c = m3;
+ c = c.replace(/^([ \t]*)/g, ""); // leading whitespace
+ c = c.replace(/[ \t]*$/g, ""); // trailing whitespace
+ c = _EncodeCode(c);
+ 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.
+ return m1 + "" + c + "
";
+ }
+ );
+
+ return text;
+ }
+
+ function _EncodeCode(text) {
+ //
+ // Encode/escape certain characters inside Markdown code runs.
+ // The point is that in code, these characters are literals,
+ // and lose their special Markdown meanings.
+ //
+ // Encode all ampersands; HTML entities are not
+ // entities within a Markdown code span.
+ text = text.replace(/&/g, "&");
+
+ // Do the angle bracket song and dance:
+ text = text.replace(//g, ">");
+
+ // Now, escape characters that are magic in Markdown:
+ text = escapeCharacters(text, "\*_{}[]\\", false);
+
+ // jj the line above breaks this:
+ //---
+
+ //* Item
+
+ // 1. Subitem
+
+ // special char: *
+ //---
+
+ return text;
+ }
+
+ function _DoItalicsAndBoldStrict(text) {
+
+ if (text.indexOf("*") === -1 && text.indexOf("_") === - 1)
+ return text;
+
+ text = asciify(text);
+
+ // must go first:
+
+ // (^|[\W_]) Start with a non-letter or beginning of string. Store in \1.
+ // (?:(?!\1)|(?=^)) Either the next character is *not* the same as the previous,
+ // or we started at the end of the string (in which case the previous
+ // group had zero width, so we're still there). Because the next
+ // character is the marker, this means that if there are e.g. multiple
+ // underscores in a row, we can only match the left-most ones (which
+ // prevents foo___bar__ from getting bolded)
+ // (\*|_) The marker character itself, asterisk or underscore. Store in \2.
+ // \2 The marker again, since bold needs two.
+ // (?=\S) The first bolded character cannot be a space.
+ // ([^\r]*?\S) The actual bolded string. At least one character, and it cannot *end*
+ // with a space either. Note that like in many other places, [^\r] is
+ // just a workaround for JS' lack of single-line regexes; it's equivalent
+ // to a . in an /s regex, because the string cannot contain any \r (they
+ // are removed in the normalizing step).
+ // \2\2 The marker character, twice -- end of bold.
+ // (?!\2) Not followed by another marker character (ensuring that we match the
+ // rightmost two in a longer row)...
+ // (?=[\W_]|$) ...but by any other non-word character or the end of string.
+ text = text.replace(/(^|[\W_])(?:(?!\1)|(?=^))(\*|_)\2(?=\S)([^\r]*?\S)\2\2(?!\2)(?=[\W_]|$)/g,
+ "$1$3");
+
+ // This is almost identical to the regex, except 1) there's obviously just one marker
+ // character, and 2) the italicized string cannot contain the marker character.
+ text = text.replace(/(^|[\W_])(?:(?!\1)|(?=^))(\*|_)(?=\S)((?:(?!\2)[^\r])*?\S)\2(?!\2)(?=[\W_]|$)/g,
+ "$1$3");
+
+ return deasciify(text);
+ }
+
+ function _DoItalicsAndBold_AllowIntrawordWithAsterisk(text) {
+
+ if (text.indexOf("*") === -1 && text.indexOf("_") === - 1)
+ return text;
+
+ text = asciify(text);
+
+ // must go first:
+ // (?=[^\r][*_]|[*_]) Optimization only, to find potentially relevant text portions faster. Minimally slower in Chrome, but much faster in IE.
+ // ( Store in \1. This is the last character before the delimiter
+ // ^ Either we're at the start of the string (i.e. there is no last character)...
+ // | ... or we allow one of the following:
+ // (?= (lookahead; we're not capturing this, just listing legal possibilities)
+ // \W__ If the delimiter is __, then this last character must be non-word non-underscore (extra-word emphasis only)
+ // |
+ // (?!\*)[\W_]\*\* If the delimiter is **, then this last character can be non-word non-asterisk (extra-word emphasis)...
+ // |
+ // \w\*\*\w ...or it can be word/underscore, but only if the first bolded character is such a character as well (intra-word emphasis)
+ // )
+ // [^\r] actually capture the character (can't use `.` since it could be \n)
+ // )
+ // (\*\*|__) Store in \2: the actual delimiter
+ // (?!\2) not followed by the delimiter again (at most one more asterisk/underscore is allowed)
+ // (?=\S) the first bolded character can't be a space
+ // ( Store in \3: the bolded string
+ //
+ // (?:| Look at all bolded characters except for the last one. Either that's empty, meaning only a single character was bolded...
+ // [^\r]*? ... otherwise take arbitrary characters, minimally matching; that's all bolded characters except for the last *two*
+ // (?!\2) the last two characters cannot be the delimiter itself (because that would mean four underscores/asterisks in a row)
+ // [^\r] capture the next-to-last bolded character
+ // )
+ // (?= lookahead at the very last bolded char and what comes after
+ // \S_ for underscore-bolding, it can be any non-space
+ // |
+ // \w for asterisk-bolding (otherwise the previous alternative would've matched, since \w implies \S), either the last char is word/underscore...
+ // |
+ // \S\*\*(?:[\W_]|$) ... or it's any other non-space, but in that case the character *after* the delimiter may not be a word character
+ // )
+ // . actually capture the last character (can use `.` this time because the lookahead ensures \S in all cases)
+ // )
+ // (?= lookahead; list the legal possibilities for the closing delimiter and its following character
+ // __(?:\W|$) for underscore-bolding, the following character (if any) must be non-word non-underscore
+ // |
+ // \*\*(?:[^*]|$) for asterisk-bolding, any non-asterisk is allowed (note we already ensured above that it's not a word character if the last bolded character wasn't one)
+ // )
+ // \2 actually capture the closing delimiter (and make sure that it matches the opening one)
+
+ text = text.replace(/(?=[^\r][*_]|[*_])(^|(?=\W__|(?!\*)[\W_]\*\*|\w\*\*\w)[^\r])(\*\*|__)(?!\2)(?=\S)((?:|[^\r]*?(?!\2)[^\r])(?=\S_|\w|\S\*\*(?:[\W_]|$)).)(?=__(?:\W|$)|\*\*(?:[^*]|$))\2/g,
+ "$1$3");
+
+ // now :
+ // (?=[^\r][*_]|[*_]) Optimization, see above.
+ // ( Store in \1. This is the last character before the delimiter
+ // ^ Either we're at the start of the string (i.e. there is no last character)...
+ // | ... or we allow one of the following:
+ // (?= (lookahead; we're not capturing this, just listing legal possibilities)
+ // \W_ If the delimiter is _, then this last character must be non-word non-underscore (extra-word emphasis only)
+ // |
+ // (?!\*) otherwise, we list two possiblities for * as the delimiter; in either case, the last characters cannot be an asterisk itself
+ // (?:
+ // [\W_]\* this last character can be non-word (extra-word emphasis)...
+ // |
+ // \D\*(?=\w)\D ...or it can be word (otherwise the first alternative would've matched), but only if
+ // a) the first italicized character is such a character as well (intra-word emphasis), and
+ // b) neither character on either side of the asterisk is a digit
+ // )
+ // )
+ // [^\r] actually capture the character (can't use `.` since it could be \n)
+ // )
+ // (\*|_) Store in \2: the actual delimiter
+ // (?!\2\2\2) not followed by more than two more instances of the delimiter
+ // (?=\S) the first italicized character can't be a space
+ // ( Store in \3: the italicized string
+ // (?:(?!\2)[^\r])*? arbitrary characters except for the delimiter itself, minimally matching
+ // (?= lookahead at the very last italicized char and what comes after
+ // [^\s_]_ for underscore-italicizing, it can be any non-space non-underscore
+ // |
+ // (?=\w)\D\*\D for asterisk-italicizing, either the last char is word/underscore *and* neither character on either side of the asterisk is a digit...
+ // |
+ // [^\s*]\*(?:[\W_]|$) ... or that last char is any other non-space non-asterisk, but then the character after the delimiter (if any) must be non-word
+ // )
+ // . actually capture the last character (can use `.` this time because the lookahead ensures \S in all cases)
+ // )
+ // (?= lookahead; list the legal possibilities for the closing delimiter and its following character
+ // _(?:\W|$) for underscore-italicizing, the following character (if any) must be non-word non-underscore
+ // |
+ // \*(?:[^*]|$) for asterisk-italicizing, any non-asterisk is allowed; all other restrictions have already been ensured in the previous lookahead
+ // )
+ // \2 actually capture the closing delimiter (and make sure that it matches the opening one)
+
+ text = text.replace(/(?=[^\r][*_]|[*_])(^|(?=\W_|(?!\*)(?:[\W_]\*|\D\*(?=\w)\D))[^\r])(\*|_)(?!\2\2\2)(?=\S)((?:(?!\2)[^\r])*?(?=[^\s_]_|(?=\w)\D\*\D|[^\s*]\*(?:[\W_]|$)).)(?=_(?:\W|$)|\*(?:[^*]|$))\2/g,
+ "$1$3");
+
+ return deasciify(text);
+ }
+
+
+ function _DoBlockQuotes(text) {
+
+ /*
+ text = text.replace(/
+ ( // Wrap whole match in $1
+ (
+ ^[ \t]*>[ \t]? // '>' at the start of a line
+ .+\n // rest of the first line
+ (.+\n)* // subsequent consecutive lines
+ \n* // blanks
+ )+
+ )
+ /gm, function(){...});
+ */
+
+ text = text.replace(/((^[ \t]*>[ \t]?.+\n(.+\n)*\n*)+)/gm,
+ function (wholeMatch, m1) {
+ var bq = m1;
+
+ // attacklab: hack around Konqueror 3.5.4 bug:
+ // "----------bug".replace(/^-/g,"") == "bug"
+
+ bq = bq.replace(/^[ \t]*>[ \t]?/gm, "~0"); // trim one level of quoting
+
+ // attacklab: clean up hack
+ bq = bq.replace(/~0/g, "");
+
+ bq = bq.replace(/^[ \t]+$/gm, ""); // trim whitespace-only lines
+ bq = _RunBlockGamut(bq); // recurse
+
+ bq = bq.replace(/(^|\n)/g, "$1 ");
+ // These leading spaces screw with content, so we need to fix that:
+ bq = bq.replace(
+ /(\s*
[^\r]+?<\/pre>)/gm,
+ function (wholeMatch, m1) {
+ var pre = m1;
+ // attacklab: hack around Konqueror 3.5.4 bug:
+ pre = pre.replace(/^ /mg, "~0");
+ pre = pre.replace(/~0/g, "");
+ return pre;
+ });
+
+ return hashBlock("
\n" + bq + "\n
");
+ }
+ );
+ return text;
+ }
+
+ function _FormParagraphs(text, doNotUnhash) {
+ //
+ // Params:
+ // $text - string to process with html