如何保留HTML <pre>标记中包含的文本的空格缩进,不包括文档中<pre>标记的当前缩进级别?

Mic*_*ton 45 html whitespace indentation pre

我正在尝试在网站上显示我的代码,但我遇到了正确保留空白缩进的问题.

例如,给出以下代码段:

<html>
 <body>
   Here is my code:
   <pre>
     def some_funtion
       return 'Hello, World!'
     end
   </pre>
 <body>
</html>
Run Code Online (Sandbox Code Playgroud)

这在浏览器中显示为:

Here is my code:

     def some_funtion
       return 'Hello, World!'
     end
Run Code Online (Sandbox Code Playgroud)

当我希望它显示为:

Here is my code:

def some_funtion
 return 'Hello, World!'
end
Run Code Online (Sandbox Code Playgroud)

区别在于HTML预标记的当前缩进级别被添加到代码的缩进中.我正在使用nanoc作为静态网站生成器,我使用谷歌美化也添加语法高亮.

有人可以提供任何建议吗?

Tim*_*ora 23

PRE旨在保留与其出现的完全相同的空白(除非white-space在CSS中进行更改,因为CSS没有足够的灵活性来支持格式化代码).

之前

保留格式,但PRE标记之外的所有缩进都是如此.使用标签位置作为起点的空白保留会很好.

在此输入图像描述

内容仍然按声明格式化,但PRE删除了由文档中标记位置引起的无关前导空格.

在此输入图像描述

我想出了以下插件来解决想要删除文档大纲缩进造成的多余空白的问题.此代码使用PRE标记内的第一行来确定它纯粹由于文档的缩进而缩进了多少.

此代码适用于IE7,IE8,IE9,Firefox和Chrome.我已经使用Prettify库对它进行了简单测试,将保留的格式与漂亮的打印相结合.确保PRE实际内部的第一行代表您想要忽略的缩进的基线级别(或者,您可以修改插件以使其更加智能).

这是粗略的代码.如果您发现错误或无法正常工作,请修改/评论; 不只是downvote.我写了这段代码来解决我遇到的问题,并且我正在积极地使用它,所以我希望它尽可能地坚固!

/*!
*** prettyPre ***/

(function( $ ) {

    $.fn.prettyPre = function( method ) {

        var defaults = {
            ignoreExpression: /\s/ // what should be ignored?
        };

        var methods = {
            init: function( options ) {
                this.each( function() {
                    var context = $.extend( {}, defaults, options );
                    var $obj = $( this );
                    var usingInnerText = true;
                    var text = $obj.get( 0 ).innerText;

                    // some browsers support innerText...some don't...some ONLY work with innerText.
                    if ( typeof text == "undefined" ) {
                        text = $obj.html();
                        usingInnerText = false;
                    }

                    // use the first line as a baseline for how many unwanted leading whitespace characters are present
                    var superfluousSpaceCount = 0;
                    var currentChar = text.substring( 0, 1 );

                    while ( context.ignoreExpression.test( currentChar ) ) {
                        currentChar = text.substring( ++superfluousSpaceCount, superfluousSpaceCount + 1 );
                    }

                    // split
                    var parts = text.split( "\n" );
                    var reformattedText = "";

                    // reconstruct
                    var length = parts.length;
                    for ( var i = 0; i < length; i++ ) {
                        // cleanup, and don't append a trailing newline if we are on the last line
                        reformattedText += parts[i].substring( superfluousSpaceCount ) + ( i == length - 1 ? "" : "\n" );
                    }

                    // modify original
                    if ( usingInnerText ) {
                        $obj.get( 0 ).innerText = reformattedText;
                    }
                    else {
                        // This does not appear to execute code in any browser but the onus is on the developer to not 
                        // put raw input from a user anywhere on a page, even if it doesn't execute!
                        $obj.html( reformattedText );
                    }
                } );
            }
        }

        if ( methods[method] ) {
            return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 ) );
        }
        else if ( typeof method === "object" || !method ) {
            return methods.init.apply( this, arguments );
        }
        else {
            $.error( "Method " + method + " does not exist on jQuery.prettyPre." );
        }
    }
} )( jQuery );
Run Code Online (Sandbox Code Playgroud)

然后可以使用标准jQuery选择器应用此插件:

<script>
    $( function() { $("PRE").prettyPre(); } );
</script>
Run Code Online (Sandbox Code Playgroud)


Dal*_*ale 17

缩进评论

由于浏览器会忽略注释,因此您可以使用它们来缩进pre标记内容.

<html>
  <body>
    <main>
      Here is my code with hack:
      <pre>
<!-- -->def some_function
<!-- -->  return 'Hello, World!'
<!-- -->end
      </pre>
      Here is my code without hack:
      <pre>
        def some_function
          return 'Hello, World!'
        end
      </pre>
    </main>
  <body>
</html>
Run Code Online (Sandbox Code Playgroud)

注意:添加了一个主包装,为注释提供了足够的空间.

好处

  • 无需JavaScript
  • 可以静态添加
  • 缩小不会影响缩进并减小文件大小

缺点

  • 要求评论的最小空间
  • 除非使用构建工具,否则不是很优雅

删除节点缩进

更好的解决方案是使用构建过程或后端渲染过程删除前导空白区域.如果您正在使用node.js,那么您可以使用我编写的名为predentation的流.您可以使用任何您想要构建类似工具的语言.

之前

<html>
 <body>
   Here is my code:
   <pre>
     def some_function
       return 'Hello, World!'
     end
   </pre>
 </body>
</html>
Run Code Online (Sandbox Code Playgroud)

<html>
 <body>
   Here is my code:
   <pre>
def some_function
  return 'Hello, World!'
end
   </pre>
 </body>
</html>
Run Code Online (Sandbox Code Playgroud)

好处

  • 无缝的方式来写pre标签
  • 较小的输出文件大小

缺点

  • 需要在工作流程中构建步骤
  • 不处理CSS添加的非pre元素white-space: pre

使用JavaScript删除缩进

请参阅此答案以使用JavaScript删除缩进

好处

  • 可以使用 white-space: pre

缺点

  • 可以禁用JavaScript
  • 空白会增加文件大小

  • 到目前为止,不是最漂亮的,而是最好的解决方案。我希望有一个解决方法,可以对data- *属性进行相同的处理(ZeroClipboard使用它来存储要复制的文本,而我使用它来存储代码段)。但是在那种情况下,评论不会被忽略。 (2认同)

use*_*702 5

使用JavaScript进行管理.它适用于Internet Explorer 9和Chrome 15,我还没有测试旧版本.当outerHTML添加支持时,它应该在Firefox 11中工作(见这里),同时网上有一些自定义实现.读者的练习是摆脱尾随缩进(直到我花时间完成它并更新这个答案).

我还将此标记为社区维基,以便于编辑.

请注意,您必须重新格式化示例以使用制表符作为缩进,或更改正则表达式以使用空格.

<!DOCTYPE html>
<html>
    <head>
        <title>Hello, World!</title>
    </head>
    <body>
        <pre>
            &lt;html&gt;
                &lt;head&gt;
                    &lt;title&gt;Hello World Example&lt;/title&gt;
                &lt;/head&gt;
                &lt;body&gt;
                    Hello, World!
                &lt;/body&gt;
            &lt;/html&gt;
        </pre>
        <pre>
            class HelloWorld
            {
                public static int Main(String[] args)
                {
                    Console.WriteLine(&amp;quot;Hello, World!&amp;quot;);
                    return 0;
                }
            }
        </pre>
        <script language="javascript">
            var pre_elements = document.getElementsByTagName('pre');

            for (var i = 0; i < pre_elements.length; i++)
            {
                var content = pre_elements[i].innerHTML;

                var tabs_to_remove = '';
                while (content.indexOf('\t') == '0')
                {
                  tabs_to_remove += '\t';
                  content = content.substring(1);
                }

                var re = new RegExp('\n' + tabs_to_remove, 'g');
                content = content.replace(re, '\n');
                pre_elements[i].outerHTML = '<pre>' + content + '</pre>';
            }
        </script>
    </body>
</html>
Run Code Online (Sandbox Code Playgroud)