【问题标题】:Can CodeMirror show Markdown line breaks?CodeMirror 可以显示 Markdown 换行符吗?
【发布时间】:2013-06-19 00:24:37
【问题描述】:

可以告诉 Markdown 模式下的 CodeMirror 显示换行符吗?

示例:下面是带有 2 个尾随空格的 Markdown 行,这意味着“我想要一个换行符”。然后是另一行没有尾随空格,这意味着“请不要换行”。但是,由于尾随空格是不可见的,如果可以绘制 来表示将插入新行,我会发现它会很有帮助。

Roses are flowers  ↵
Violets are also flowers
and wise mice slice rice

这将呈现为:

Roses are flowers
Violets are also flowers and wise mice slice rice

【问题讨论】:

  • 好吧,你可以edit the markdown mode 来做到这一点。使用源,卢克。
  • @EliranMalka 我最后写了一个 CodeMirror 插件。在此页面上查看我的答案。也许最好不要碰 Markdown 模式本身——我不得不合并来自主 repo @ Github 的更改以使其保持最新。
  • 听起来是个好主意。你回馈了吗?
  • @EliranMalka 我已将 an email 发送到 Google 邮件组,其中包含指向源代码(MIT 许可)和演示的链接,所以是的,我想我做到了。

标签: javascript markdown codemirror


【解决方案1】:

这是一个简单的叠加层,将设置尾随空格的样式:

editorInstance.addOverlay({
  token: function(stream) {
    if (stream.match(/^\s+$/)) return "trailing-whitespace";
    stream.match(/^\s*\S*/);
    return null;
  }
});

然后添加这样的 CSS 规则以使其真正可见:

.cm-trailing-whitespace { color: #f80; text-decoration: underline; }

【讨论】:

  • 谢谢玛丽恩!我将在升级到 CodeMirror 3 后立即对此进行测试(我的版本中似乎没有 .addOverlay,一些旧的 2.x 版本)。
  • 我现在已经升级到 3.13,并且我测试了 [样式化尾随空格的覆盖]。但是,我认为很难判断是否有 1 个或 2 个尾随空格,因此我编写了另一个叠加层,而不是使用专用标记为每个空格设置样式 - 请在此页面上查看我自己的答案。 (尾随空格覆盖将所有尾随空格包裹在单个 中,这使得很难单独设置每个空格的样式)
【解决方案2】:

我编写了一个 MarkDown 叠加层,它通过以下方式可视化换行符: · ↵(第一个空格是“·”,第二个空格是“↵”)。示例:

Violets are flowers·↵
Roses are also flowers

(第一行有 2 个尾随空格。)

这是一个演示和最新源代码文件的链接:(许可证:MIT)
http://www.debiki.com/-1c250-visualizing-markdown-double-space-line-breaks


使用示例:包含上面的 JS 和 CSS 文件,并且:

var codeMirrorEditor = CodeMirror.fromTextArea(some-textarea, {
  mode: "markdown",
  showMarkdownLineBreaks: true,   // <---
  ...
});


源代码,截至今天:先是 CSS,然后是 JS:

------------ CSS:

/**
 * Makes the CodeMirror editor show newlines, in Markdown mode.
 *
 * Copyright (C) 2013 Kaj Magnus Lindberg (born 1979)
 *
 * Licensed under the MIT license.
 */

.cm-markdown-single-trailing-space-odd:before,
.cm-markdown-single-trailing-space-even:before,
.cm-markdown-line-break:before {
  font-weight: bold;
  color: hsl(30, 100%, 50%); /* a dark orange */
  position: absolute;
}


.cm-markdown-single-trailing-space-odd:before,
.cm-markdown-single-trailing-space-even:before {
  content: '·';
}

.cm-markdown-line-break:before {
  content: '↵';
}

------------ JS:

/**
 * Shows trailing Markdown spaces and line breaks, like so:·↵
 *
 * Copyright (C) 2013 Kaj Magnus Lindberg (born 1979)
 *
 * License: (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */


CodeMirror.defineOption("showMarkdownLineBreaks", false,
    function(codeMirror, newValue, oldValue) {

  if (oldValue == CodeMirror.Init) {
    oldValue = false;
  }
  if (oldValue && !newValue) {
    codeMirror.removeOverlay("show-markdown-line-breaks");
  }
  else if (!oldValue && newValue) {
    codeMirror.addOverlay({
      name: "show-markdown-line-breaks",
      token: markMarkdownTrailingSpaces
    });
  }
});


function markMarkdownTrailingSpaces(stream) {

  // Possible stream.string:s and how they're handled: (`n` is text
  // with no trailing spaces)
  // ""
  // "n"    case 1
  // "_"    case 3
  // "n_"   case 1, case 3
  // "__"   case 2, case 3
  // "n__"  case 1, case 2, case 3
  // "___"  case 2, case 3
  // "n___" case 1, case 2, case 3

  // Returns separate CSS classes for each trailing space;
  // otherwise CodeMirror merges contiguous spaces into
  // one single <span>, and then I don't know how to via CSS
  // replace each space with exact one '·'.
  function singleTrailingSpace() {
    return stream.pos % 2 == 0 ?
      "markdown-single-trailing-space-even" :
      "markdown-single-trailing-space-odd";
  };

  if (!stream.string.length) // can this happen?
    return null;

  // Case 1: Non-space characters. Eat until last non-space char.
  var eaten = stream.match(/.*[^ ]/);
  if (eaten)
    return null;

  // Case 2, more than one trailing space left before end-of-line.
  // Match one space at a time, so each space gets its own
  // `singleTrailingSpace()` CSS class. Look-ahead (`(?=`) for more spaces.
  if (stream.match(/ (?= +$)/))
    return singleTrailingSpace();

  // Case 3: the very last char on this line, and it's a space.
  // Count num trailing spaces up to including this last char on this line.
  // If there are 2 spaces (or more), we have a line break.
  var str = stream.string;
  var len = str.length;
  var twoTrailingSpaces = len >= 2 && str[len - 2] == ' ';
  stream.eat(/./);
  if (twoTrailingSpaces)
    return "markdown-line-break";
  return singleTrailingSpace();
};


// vim: et ts=2 sw=2 list

【讨论】:

  • 请附上一个简洁的示例(或实际发挥作用的代码部分),以便获得一个独立的答案。
  • @EliranMalka 我添加了一个使用示例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-23
  • 2014-08-22
  • 1970-01-01
  • 2012-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多