问题
Is it possible to wrap indented code on a web page the way it's done in a code editor? See the screenshot comparison below to better understand what I mean:
pre-wrap
on a web page:
![](https://www.eimg.top/images/2020/03/17/ae0199d7d4d171d04ea407ed37cabaee.png)
Wrapping of indented lines in a code editor:
![](https://www.eimg.top/images/2020/03/17/27a7deb3f1b657fd1b23cc6060153ffb.png)
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.
回答1:
Algorithm
- Get the contents of the element, and generate a list of all lines.
- Use the element to measure the width of a space character.
- Create a document fragment (for optimal performance!).
- 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
(orpaddingLeft
, 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).
- Replace the contents of the actual element with the fragment.
Code (demo: http://jsfiddle.net/YPnhX/):
/**
* Auto-indent overflowing lines
* @author Rob W http://stackoverflow.com/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 compatibility
- 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.
来源:https://stackoverflow.com/questions/11562465/indent-code-on-a-web-page-like-in-a-code-editor