Как сохранить отступы текста, заключенного в теги HTML <pre>, без учета текущего уровня отступа тега <pre>в документе? - PullRequest
43 голосов
/ 08 января 2011

Я пытаюсь отобразить свой код на веб-сайте, но у меня возникают проблемы с правильным сохранением отступа пробела.

Например, учитывая следующий фрагмент:

<code><html>
 <body>
   Here is my code:
   <pre>
     def some_funtion
       return 'Hello, World!'
     end
   

Это отображается в браузере как:

Here is my code:

     def some_funtion
       return 'Hello, World!'
     end

Когда я хотел бы, чтобы это отображалось как:

Here is my code:

def some_funtion
 return 'Hello, World!'
end

Разница в том, что текущий уровень отступа предварительного тега HTML добавляется к отступу кода. Я использую Nanoc в качестве статического генератора веб-сайтов и использую Google Prettify, чтобы также добавить подсветку синтаксиса.

Может кто-нибудь предложить какие-либо предложения?

Ответы [ 10 ]

23 голосов
/ 20 февраля 2012

PRE предназначен для сохранения пробелов в точности так, как он выглядит (если только он не изменен на white-space в CSS, который не обладает достаточной гибкостью для поддержки форматирования кода).

До

Форматирование сохраняется, но все отступы за пределами тега PRE сохраняются.Было бы неплохо сохранить пробельные символы, которые использовали бы расположение тега в качестве отправной точки.

enter image description here

После

Содержаниевсе еще отформатирован как объявлено, но лишние начальные пробелы, вызванные положением тега PRE в документе, удаляются.

enter image description here

Я создал следующий плагин длярешить проблему с желанием удалить лишние пробелы, вызванные отступом контура документа.Этот код использует первую строку внутри тега PRE, чтобы определить, насколько он был отступ только из-за отступа в документе.

Этот код работает в IE7, IE8, IE9, Firefox и Chrome.Я кратко проверил это с библиотекой Prettify , чтобы объединить сохраненное форматирование с красивой печатью.Убедитесь, что первая строка внутри PRE фактически представляет базовый уровень отступа, который вы хотите игнорировать (или вы можете изменить плагин, чтобы сделать его более интеллектуальным).

Это грубый код,Если вы обнаружили ошибку или она работает не так, как вы хотите, пожалуйста, исправьте / прокомментируйте;не просто понизитьЯ написал этот код, чтобы исправить проблему, с которой столкнулся, и я активно его использую, поэтому мне бы хотелось, чтобы он был максимально надежным!

/*!
*** 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 );

Затем этот плагин можно применить сстандартный селектор jQuery:

<script>
    $( function() { $("PRE").prettyPre(); } );
</script>
14 голосов
/ 24 мая 2015

Отступ с комментариями

Поскольку браузеры игнорируют комментарии, их можно использовать для отступа содержимого тега pre.

Решение


  
    
      Here is my code with hack:
      
<!-- -->def some_function
<!-- -->  return 'Hello, World!'
<!-- -->end
      
Вот мой код без взлома:
        def some_function
          return 'Hello, World!'
        end
      

ПРИМЕЧАНИЕ: была добавлена ​​основная оберткачтобы обеспечить достаточно места для комментариев.

Преимущества

  • Не требуется JavaScript
  • Может быть добавлен статически
  • Минификация не будетвлияет на отступ и уменьшает размер файла

Недостатки

  • Требуется минимальное количество места для комментариев
  • Не очень элегантно, если не используются инструменты сборки

Удаление отступов с помощью узла

Лучшим решением является удаление начальных пробелов с использованием процесса сборки или процесса рендеринга на стороне сервера.Если вы используете node.js, вы можете использовать поток, который я написал, под названием predentation .Вы можете использовать любой язык для создания аналогичного инструмента.

До


 
   Here is my code:
   
     def some_function
       return 'Hello, World!'
     end
   

После


 
   Here is my code:
   
def some_function
  return 'Hello, World!'
end
   

Преимущества

  • Простой способ записи pre тегов
  • Меньший размер выходного файла

Недостатки

  • Требуется этап сборки в вашем рабочем процессе
  • Не обрабатывает элементы не pre с white-space: pre, добавленные CSS

Удаление отступов с помощьюJavaScript

См. Этот ответ для удаления отступов с помощью JavaScript

Преимущества

  • Возможно нацеливание элементов с помощью white-space: pre

Недостатки

  • JavaScript можно отключить
  • Пробел увеличивает размер файла
5 голосов
/ 14 декабря 2011

Удалось сделать это с помощью JavaScript. Он работает в Internet Explorer 9 и Chrome 15, я не тестировал старые версии. Он должен работать в Firefox 11, когда добавлена ​​поддержка outerHTML (см. здесь ), в то время как в Интернете есть несколько пользовательских реализаций. Упражнение для читателя - избавиться от конечного отступа (пока я не найду время, чтобы закончить его и обновить этот ответ).

Я также отмечу это как вики сообщества для удобного редактирования.

Обратите внимание, что вам придется переформатировать пример для использования вкладок в качестве отступа или изменить регулярное выражение для работы с пробелами.

<code><!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;
        
            class HelloWorld
            {
                public static int Main(String[] args)
                {
                    Console.WriteLine(&amp;quot;Hello, World!&amp;quot;);
                    return 0;
                }
            }
        
var pre_elements = document.getElementsByTagName ('pre'); для (var i = 0; i
' + content + '
'; }
3 голосов
/ 31 июля 2015

Это можно сделать в четырех строках JavaScript:

var pre= document.querySelector('pre');

//insert a span in front of the first letter.  (the span will automatically close.)
pre.innerHTML= pre.textContent.replace(/(\w)/, '<span>$1');

//get the new span's left offset:
var left= pre.querySelector('span').getClientRects()[0].left;

//move the code to the left, taking into account the body's margin:
pre.style.marginLeft= (-left + pre.getClientRects()[0].left)+'px';
 
   Here is my code:
   
     def some_funtion
       return 'Hello, World!'
     end
   
2 голосов
/ 20 апреля 2016

<script>
    $("pre[name='pre']").each(function () {
        var html = $(this).html()
        var blankLen = (html.split('\n')[0].match(/^\s+/)[0]).length
        $(this).html($.trim(html.replace(eval("/^ {" + blankLen + "}/gm"), "")))
    })
</script>

	
		1
			2
				3
	
2 голосов
/ 01 августа 2015

Я решил придумать что-то более конкретное, чем изменение способа работы pre или code.Поэтому я сделал несколько регулярных выражений, чтобы получить первый символ новой строки \n (с предшествующим возможным пробелом - \s* используется для очистки лишних пробелов в конце строки кода и перед символом новой строки (который, как я заметил, у вас был)) и найдите символы табуляции или пробелы, следующие за ним [\t\s]* (что означает символ табуляции, символ пробела (0 или более) и установите это значение для переменной. Затем эта переменная используется в функции замены регулярного выражения, чтобы найти все ее экземплярыи замените его на \n (перевод строки). Поскольку вторая строка (где устанавливается pattern) не имеет глобального флага (g после регулярного выражения), он найдет первый экземпляр \n символ новой строки и установите переменную pattern на это значение. Таким образом, в случае символа новой строки, за которым следуют 2 символа табуляции, значение pattern будет технически равным \n\t\t, которое будет заменяться в каждом \nсимвол находится в этом элементе pre code (поскольку он проходит через каждую функцию) и заменяется на \n

$("pre code").each(function(){
    var html = $(this).html();
    var pattern = html.match(/\s*\n[\t\s]*/);
    $(this).html(html.replace(new RegExp(pattern, "g"),'\n'));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<body>
    Here is some code:

    <pre><code>
        Here is some fun code!
        More code
          One tab
            One more tab
            
            Two tabs and an extra newline character precede me
    
1 голос
/ 01 апреля 2015

Я также обнаружил, что если вы используете haml, вы можете использовать метод preserve.Например:

preserve yield

Это сохранит пробел в произведенном yield, который обычно является уценкой, содержащей блоки кода.

0 голосов
/ 22 ноября 2017

Если вы используете это в кодовом блоке, например:

<pre>
  <code>
    ...
  

Вы можете просто использовать css как этот, чтобы компенсировать это большое пространство пробела впереди.

pre code {
  position: relative;
  left: -95px; // or whatever you want
}
0 голосов
/ 03 апреля 2015

Это громоздко, но работает, если для вас важно сворачивание кода:

<code>        <pre>def some_funtion
    return 'Hello, World!'
end

В вашем css,

    pre { margin:0 }

В vim вы обычно пишете свой код и затем выполняете:

    :s/\t\t\([^\n]\+\)/<pre>\1<\/pre>/

для каждой строки будет работать.

0 голосов
/ 30 января 2014

Предварительный тег сохраняет все пробелы, которые вы использовали при записи в теле. Где, как обычно, если вы не используете pre, он будет отображать текст нормально ... (HTML заставит браузер игнорировать эти пробелы) Здесь попробуйте это, я использовал тег абзаца. Выход: -

Вот мой код:

def some_function

  return 'Hello, World!'<br>

конец

<html> <body> Here is my code: <p> def some_function<br> <pre> return 'Hello, World!'<br></pre> end </p> </body> </html>
...