Markdown If Needed

在需要的地方启用MarkDown语法,添加格式帮助链接及 Markdown 工具栏

As of 2017-04-23. See the latest version.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name        Markdown If Needed
// @namespace   wdssmq
// @description 在需要的地方启用MarkDown语法,添加格式帮助链接及 Markdown 工具栏
// @author      沉冰浮水
// @contributor JixunMoe
// @contributor wOxxOm
// @license     MIT License
// @include     https://*
// @include     http://*
// @version     1.0.0
// @grant       GM_addStyle
// ==/UserScript==

/* jshint multistr:true */
function $n(e) {
  return document.querySelector(e);
}
function $na(e) {
  return document.querySelectorAll(e);
}

function xml2md(xml) {
  var md = xml;
  if (xml.indexOf("isXML") > -1) {
    // 移除isXML
    md = md.replace(/\n?<!--isXML-->/g, "");
    //行内

    //链接
    md = md.replace(/<a href="([^"]+)" title="([^"]+)"\s*([^>]*)>(.+)<\/a>/g,'[$4]($1 "$2"){$3}');
    //图片
    md = md.replace(/<img src="([^"]+)" alt="([^"]+)"[^>]*>/g,'![$2]($1)');
    // 段落
    md = md.replace(/<p>/g, "");
    md = md.replace(/<\/p>/g, "\n\n");
    // h1-h6
    md = md.replace(/<h6>(.+?)<\/h6>/g, "###### $1\n\n");
    md = md.replace(/<h5>(.+?)<\/h5>/g, "##### $1\n\n");
    md = md.replace(/<h4>(.+?)<\/h4>/g, "#### $1\n\n");
    md = md.replace(/<h3>(.+?)<\/h3>/g, "### $1\n\n");
    md = md.replace(/<h2>(.+?)<\/h2>/g, "## $1\n\n");
    md = md.replace(/<h1>(.+?)<\/h1>/g, "# $1\n\n");
    // 格式化换行
    md = md.replace(/\n\n+/g, "\n\n");
    md = md.replace(/\n+$/g, "");
    //修正
    md = md.replace(/\){}/g, ")");
  }
  return md;
}

function md2xml(md) {
  var xml = md;
  if (md.indexOf("isXML") == -1) {
    // 格式化换行
    xml = xml.replace(/\n\n+/g, "\n\n");
    xml = xml.replace(/\n+$/g, "");
    // h1-h6
    xml = xml.replace(/(^|\n)######\s*([^\n]+)/g, "$1<h6>$2</h6>");
    xml = xml.replace(/(^|\n)#####\s*([^\n]+)/g, "$1<h5>$2</h5>");
    xml = xml.replace(/(^|\n)####\s*([^\n]+)/g, "$1<h4>$2</h4>");
    xml = xml.replace(/(^|\n)###\s*([^\n]+)/g, "$1<h3>$2</h3>");
    xml = xml.replace(/(^|\n)##\s*([^\n]+)/g, "$1<h2>$2</h2>");
    xml = xml.replace(/(^|\n)#\s*([^\n]+)/g, "$1<h1>$2</h1>");
    // 段落
    xml = xml.replace(/^(?!(<h|<p|<div))/g, "<p>");
    xml = xml.replace(/\n+(<h|<p|<div)/g, "</p>\n$1");
    xml = xml.replace(/\n\n/g, "</p>\n<p>");
    xml = xml.replace(/(p>|h\d>|div>)<\/p>/g, "$1");
    xml = xml.replace(/<p>$/g, "");
    xml = xml.replace(/<p>(?!<\/p>)(.+)$/g, "<p>$1</p>");
    // 行内标记
    xml = xml.replace(/([^\*]*)\*\*(.*)\*\*/g, "$1<b>$2</b>");
    xml = xml.replace(/([^\*]*)\*(.*)\*/g, "$1<i>$2</i>");
    //图片
    xml = xml.replace(/!\[([^\]]+)\]\(([^\s\)]+)[^\)]*\)/g, '<img src="$2" alt="$1" title="$1">');
    console.log(xml);
    //链接
    xml = xml.replace(/\[(.+)\]\(([^\s\)]+)\s*"?([^"]+)*"?\)(?:{([^}]+)})?/g, '<a href="$2" title="$3" $4>$1</a>');
    xml = xml.replace(/title=""/g,'title="点击链接查看"');
    // xml = xml.replace(/\[(.+)\]\(([^\s\)]+)\)/g, '<a href="$2">$1</a>');

    //修正
    xml = xml.replace(/\s>/g,'>');
    xml = xml.replace(/2xml/g,"");
    // 添加 isXML
    xml += "\n<!--isXML-->";
  }
  return xml;
}

window.addEventListener('DOMContentLoaded', function (e) {
  var domTxa = $n("textarea.md-needed");

  if (!domTxa)
    return;
  domTxa.addEventListener('keyup', function () {
    if(domTxa.value.indexOf("2xml") > -1)
      domTxa.value = md2xml(domTxa.value);
  });
  $n("input[type=submit]").addEventListener('mouseenter', function () {
    domTxa.value = md2xml(domTxa.value);
  });
  $n("input[type=submit]").addEventListener('mouseout', function () {
    domTxa.value = xml2md(domTxa.value);
  });

  //添加工具栏
  addFeatures(domTxa);

  GM_addStyle('\
    .md-button {\
    display: inline-block;\
    cursor: pointer;\
    margin: 0px;\
    font-size: 12px;\
    line-height: 1;\
    font-weight: bold;\
    padding: 4px 6px;\
    background: -moz-linear-gradient(center bottom , #CCC 0%, #FAFAFA 100%) repeat scroll 0% 0% #F8F8F8;\
    border: 1px solid #999;\
    border-radius: 2px;\
    white-space: nowrap;\
    text-shadow: 0px 1px 0px #FFF;\
    box-shadow: 0px 1px 0px #FFF inset, 0px -1px 2px #BBB inset;\
    color: #333;}');
});

function addFeatures(n) {
  if (!n)
    return;
  // add buttons
  // btnMake(n, '<b>Test</b>', "test", function (e) {
  // n.value = md2xml(n.value)
  // });
  btnMake(n, '<b>' + __('B') + '</b>', __('Bold'), '**');
  btnMake(n, '<i>' + __('I') + '</i>', __('Italic'), '*');
  btnMake(n, '<u>' + __('U') + '</u>', __('Underline'), '<u>', '</u>');
  btnMake(n, '<s>' + __('S') + '</s>', __('Strikethrough'), '<s>', '</s>');
  btnMake(n, '&lt;br&gt;', __('Force line break'), '<br>', '', true);
  btnMake(n, '---', __('Horizontal line'), '\n\n---\n\n', '', true);
  btnMake(n, __('URL'), __('Add URL to selected text'),
    function (e) {
    try {
      edWrapInTag('[', '](' + prompt(__('URL') + ':') + ')', edInit(e.target));
    } catch (ex) {}
  });
  btnMake(n, __('Image (https)'), __('Convert selected https://url to inline image'), '![' + __('image') + '](', ')');
  btnMake(n, __('Table'), __('Insert table template'), __('\n| head1 | head2 |\n|-------|-------|\n| cell1 | cell2 |\n| cell3 | cell4 |\n'), '', true);
  btnMake(n, __('Code'), __('Apply CODE markdown to selected text'),
    function (e) {
    var ed = edInit(e.target);
    if (ed.sel.indexOf('\n') < 0)
      edWrapInTag('`', '`', ed);
    else
      edWrapInTag(((ed.sel1 === 0) || (ed.text.charAt(ed.sel1 - 1) == '\n') ? '' : '\n') + '```' + (ed.sel.charAt(0) == '\n' ? '' : '\n'),
        (ed.sel.substr(-1) == '\n' ? '' : '\n') + '```' + (ed.text.substr(ed.sel2, 1) == '\n' ? '' : '\n'),
        ed);
  });
}

function btnMake(elTxa, label, title, tag1_or_cb, tag2, noWrap) {
  var a = document.createElement('a');
  a.className = 'md-button';
  a.innerHTML = label;
  a.title = title;
  a.style.setProperty('float', 'right');
  a.addEventListener('click',
    typeof(tag1_or_cb) == 'function' ? tag1_or_cb
     : noWrap ? function (e) {
    edInsertText(tag1_or_cb, edInit(e.target));
  }
     : function (e) {
    edWrapInTag(tag1_or_cb, tag2, edInit(e.target));
  });
  var elToolbar = elTxa.parentNode.querySelector('.md-toolbar');
  // console.log(elToolbar);
  a.textAreaNode = elTxa;
  elToolbar.insertBefore(a, elToolbar.firstElementChild);
}

function edInit(btn) {
  var ed = {
    node: btn.textAreaNode
  };
  ed.sel1 = ed.node.selectionStart;
  ed.sel2 = ed.node.selectionEnd,
  ed.text = ed.node.value;
  ed.sel = ed.text.substring(ed.sel1, ed.sel2);
  return ed;
}

function edWrapInTag(tag1, tag2, ed) {
  ed.node.value = ed.text.substr(0, ed.sel1) + tag1 + ed.sel + (tag2 ? tag2 : tag1) + ed.text.substr(ed.sel2);
  ed.node.setSelectionRange(ed.sel1 + tag1.length, ed.sel1 + tag1.length + ed.sel.length);
  ed.node.focus();
}

function edInsertText(text, ed) {
  ed.node.value = ed.text.substr(0, ed.sel2) + text + ed.text.substr(ed.sel2);
  ed.node.setSelectionRange(ed.sel2 + text.length, ed.sel2 + text.length);
  ed.node.focus();
}

var __ = (function (l, langs) {
  var lang = langs[l] || langs[l.replace(/-.+/, '')];
  return lang ? function (text) {
    return lang[text] || text;
  }
   : function (text) {
    return text;
  }; // No matching language, fallback to english
})("zh-CN", {
  // Can be full name, or just the beginning part.
  'zh-CN': {
    'Bold': '粗体',
    'Italic': '斜体',
    'Underline': '下划线',
    'Strikethrough': '删除线',
    'Force line break': '强制换行',
    'Horizontal line': '水平分割线',
    'URL': '链接',
    'Add URL to selected text': '为所选文字添加链接',
    'Image (https)': '图片 (https)',
    'Convert selected https://url to inline image': '将所选地址转换为行内图片',
    'image': '图片描述', // Default image alt value
    'Table': '表格',
    'Insert table template': '插入表格模板',
    'Code': '代码',
    'Apply CODE markdown to selected text': '将选中代码围起来',

    '\n| head1 | head2 |\n|-------|-------|\n| cell1 | cell2 |\n| cell3 | cell4 |\n':
    '\n| 表头 1 | 表头 2 |\n|-------|-------|\n| 表格 1 | 表格 2 |\n| 表格 3 | 表格 4 |\n'
  },
  'ru': {
    'B': 'Ж',
    'I': 'К',
    'U': 'Ч',
    'S': 'П',
    'Bold': 'Жирный',
    'Italic': 'Курсив',
    'Underline': 'Подчеркнутый',
    'Strikethrough': 'Перечеркнутый',
    'Force line break': 'Новая строка',
    'Horizontal line': 'Горизонтальная линия',
    'URL': 'ссылка',
    'Add URL to selected text': 'Добавить ссылку к выделенному тексту',
    'Image (https)': 'Картинка (https)',
    'Convert selected https://url to inline image': 'Преобразовать выделенный https:// адрес в картинку',
    'image': 'картинка', // Default image alt value
    'Table': 'Таблица',
    'Insert table template': 'Вставить шаблон таблицы',
    'Code': 'Код',
    'Apply CODE markdown to selected text': 'Пометить выделенный фрагмент как программный код',

    '\n| head1 | head2 |\n|-------|-------|\n| cell1 | cell2 |\n| cell3 | cell4 |\n':
    '\n| заголовок1 | заголовок2 |\n|-------|-------|\n| ячейка1 | ячейка2 |\n| ячейка3 | ячейка4 |\n'
  },
  'fr': {
    'B': 'G',
    'I': 'I',
    'U': 'S',
    'S': 'B',
    'Bold': 'Gras',
    'Italic': 'Italique',
    'Underline': 'Souligné',
    'Strikethrough': 'Barré',
    'Force line break': 'Forcer le saut de ligne',
    'Horizontal line': 'Ligne horizontale',
    'URL': 'URL',
    'Add URL to selected text': 'Ajouter URL au texte sélectionné',
    'Image (https)': 'Image (https)',
    'Convert selected https://url to inline image': 'Convertir https://url sélectionnés en images',
    'image': 'image', // Default image alt value
    'Table': 'Tableau',
    'Insert table template': 'Insérer un modèle de table',
    'Code': 'Code',
    'Apply CODE markdown to selected text': 'Appliquer CODE markdown au texte sélectionné',

    '\n| head1 | head2 |\n|-------|-------|\n| cell1 | cell2 |\n| cell3 | cell4 |\n':
    '\n| En-tête 1 | En-tête 2 |\n|-------|-------|\n| cellule 1 | cellule 2 |\n| cellule 3 | cellule 4 |\n'
  }
});