admin管理员组

文章数量:1420929

Is it possible to wrap indented code on a web page the way it's done in a code editor? See the screenshot parison below to better understand what I mean:

pre-wrap on a web page:

Wrapping of indented lines in a code editor:

What I am implying is that the indented lines maintain indentation even after wrapping. This doesn't seem to happen on web pages. Is there a CSS property that does this? (JavaScript would be fine too.)

NOTE: I am not talking about code highlighting here. It's about indentation of wrapped lines.


If this matters — this is how I am showing code blocks on my web pages:

<pre><code>if ( is_page() && $post->post_parent ) {
  return $post->post_parent;

} else {
  return false;
}
</code></pre>

...and the white-space: pre-wrap; style is applied on pre tag.

Is it possible to wrap indented code on a web page the way it's done in a code editor? See the screenshot parison below to better understand what I mean:

pre-wrap on a web page:

Wrapping of indented lines in a code editor:

What I am implying is that the indented lines maintain indentation even after wrapping. This doesn't seem to happen on web pages. Is there a CSS property that does this? (JavaScript would be fine too.)

NOTE: I am not talking about code highlighting here. It's about indentation of wrapped lines.


If this matters — this is how I am showing code blocks on my web pages:

<pre><code>if ( is_page() && $post->post_parent ) {
  return $post->post_parent;

} else {
  return false;
}
</code></pre>

...and the white-space: pre-wrap; style is applied on pre tag.

Share Improve this question edited Jan 10, 2013 at 6:26 Jonathan Leffler 756k145 gold badges951 silver badges1.3k bronze badges asked Jul 19, 2012 at 13:57 its_meits_me 11.4k25 gold badges87 silver badges135 bronze badges 14
  • 1 You have to wrap the "code" (text) in another container, and indent the container. – Rob W Commented Jul 19, 2012 at 14:00
  • 3 A close vote and a down vote? This is a CSS question. Can someone please clarify? – its_me Commented Jul 19, 2012 at 14:11
  • 2 It's not possible using pure CSS. Do you allow JavaScript? – Rob W Commented Jul 20, 2012 at 20:11
  • 1 @RobW Yes! I already use JavaScript to highlight code blocks, so a little more JS isn't going to hurt. :) – its_me Commented Jul 21, 2012 at 0:59
  • 1 @PauloScardine But isn't it difficult to scan & understand code when scrolling horizontally? (As for SO, when there's code that I have to scroll horizontally, I simply copy it into my text editor, that way I am able to understand better—due to proper indentation as shown above) – its_me Commented Jul 21, 2012 at 13:27
 |  Show 9 more ments

1 Answer 1

Reset to default 7 +50

Algorithm

  1. Get the contents of the element, and generate a list of all lines.
  2. Use the element to measure the width of a space character.
  3. Create a document fragment (for optimal performance!).
  4. Loop through all lines. For each line:
    • Count the number of preceeding white space.
    • Create a block-level element (such as <div>).
    • Set the marginLeft (or paddingLeft, if you wish) property to the product of the size of a single space and the number of prefixed spaces.
    • Append The contents of the line (left trimmed).
  5. Replace the contents of the actual element with the fragment.

Code (demo: http://jsfiddle/YPnhX/):

/**
 * Auto-indent overflowing lines
 * @author Rob W http://stackoverflow./u/938089
 * @param code_elem HTMLCodeElement (or any element containing *plain text*)
 */
function autoindent(code_elem) {
    // Grab the lines
    var textContent = document.textContent === null ? 'textContent' : 'innerText';
    var lines = code_elem[textContent].split(/\r?\n/),
        fragment = document.createDocumentFragment(),
        dummy, space_width, i, prefix_len, line_elem;

    // Calculate the width of white space
    // Assume that inline element inherit styles from parent (<code>)
    dummy = document.createElement('span');
    code_elem.appendChild(dummy);
    // offsetWidth includes padding and border, explicitly override the style:
    dummy.style.cssText = 'border:0;padding:0;';
    dummy[textContent] = ' ';
    space_width = dummy.offsetWidth;
    // Wipe contents
    code_elem.innerHTML = '';

    for (i=0; i<lines.length; i++) {
        // NOTE: All preceeding white space (including tabs is included)
        prefix_len = /^\s*/.exec(lines[i])[0].length;
        line_elem = fragment.appendChild(document.createElement('div'));
        line_elem.style.marginLeft = space_width * prefix_len + 'px';
        line_elem[textContent] = lines[i].substring(prefix_len);
    }
    // Finally, append (all elements inside) the fragment:
    code_elem.appendChild(fragment);
}

Browser patibility

  • IE8 + (IE7- doesn't support white-space:pre-wrap)
  • Chrome 1+
  • Firefox 3+
  • Safari 3+
  • Opera 9+ (previous versions untested)

Notes

  • In this example, I calculated the width of a space (U+0020) character. The similar method is used if you want to calculate different values for other white-space characters.
  • Follow-up to the previous note: To account for tabs, you have to take a hard route, which degrades performance. For each line, set the contents of the dummy (appended to code_elem!) to the prefixed white space, then calculate the width using .offsetWidth.
    Each time, the element is rendered. For hundreds of lines, this method may cause a spike in the CPU usage. Don't ever use tabs to display code in a web page!
  • The autoindent function assumes that the contents of a element is plain text.

本文标签: javascriptIndent code on a web page like in a code editorStack Overflow