In my Angular 1.x application (using ES5) I need to show the user the sample of formatted css and js code on the UI (with indentations, line-breaks, etc.), which the the user will need to copy and paste into his own html file. The sample of code:
<style type='text/css'> html, body { margin: 0 }
.banner {
display: block;
position: absolute;
</style>
<script>
window.showSmth = function(item) {
// some logic here
}
</script>
I've tried to search for some 3rd parties, but no results so far, could someone advice me on this?
In HTML proper, there’s no way short of escaping the characters.
The only solution guaranteed to work everywhere is to escape the code (< and & as < and &, respectively) manually.
Replace the & character with &
Replace the < character with <
Replace the > character with >
Optionally surround your HTML sample with <pre> and/or <code> tags.
Syntax highlighting sites:
rainbows (very Perfect)
prettify
syntaxhighlighter
highlight
JSHighlighter
Related
Default strikethrough functionality of CKEditor works well and do what is logic, adding an "s" tag surrounding the text that has strikethrough (also I can make the editor use html5's "del" tag), the problem however, is that assistive reading technologies such as NVDA or JAWS do not read this kind of content in any way different from normal text without special settings. What I'm trying to do is to add a span tag at the beginning and at the end of strikethrough text indicating this fact to the user:
<p>
<span style="height: 1px; width: 1px; position: absolute; overflow: hidden; top: -10px;">Start strikethrough. </span>
<s>Text with strikethrough</s>
<span style="height: 1px; width: 1px; position: absolute; overflow: hidden; top: -10px;">End strikethrough. </span>
</p>
As you can see in this code the span is not visible in the page but the reader will follow dom order so the user will be alerted of the strikethrough.
I know you can build a plugin to insert any html but I have to make this work in the same way basic styles buttons work, with toggle feature:
The easy part: if there is a selection in the content and the button is pressed we have to strikethrough the content. This one is easier as we can get the selected html and surround it with what I want.
The harder part: if there is no selection and the button is pressed then every text written next must have the strikethrough.
After lot of researching and analysing how the "real" plugin was made I came to something like this:
CKEDITOR.plugins.add( 'customStrike', {
icons: 'customStrike',
init: function( editor ) {
var style = new CKEDITOR.style( { element: 's' } );
editor.attachStyleStateChange( style, function (state) {
!editor.readOnly && editor.getCommand( 'customStrike').setState(state);
} );
editor.addCommand( 'customStrike', new CKEDITOR.styleCommand( style ) );
if ( editor.ui.addButton ) {
editor.ui.addButton( 'CustomStrike', {
label: 'Strike Through',
command: 'customStrike',
toolbar: 'custom'
} );
}
}
});
This works exactly as the real plugin, I tried to work around this code but the element property in the style defintion only accepts one tag as far as I know, I would need a way to nest tags using the element property to accomplish this.
Is there any way to solve this?
Any help would be appreciated.
For me it looks like you're trying to fix the wrong end of the problem. It's readers' problem that they don't read the content differently. Clobbering the content may help for a while (although it will break the editing), but will be a problem when the readers are updated and start reading the content properly.
Anyway, if you insist on having some solution right now, then I have two advices:
There may be some ARIA role or other attribute that you could set on the s/del tag which will somehow affect the readers.
Do not clobber the content inside the editor, because you will break it. You could for example process the content before sending it to the end user, if that's the part that you want to fix.
I have long namespaces to be displayed in my articles (like MyProject\Sub\Level) and I want them to be wrapped on a backslash character (\) if the window width is insufficient. How can I implement this using CSS or JS/jQuery?
To tell browsers that a line break is permitted after a character, insert the ZERO WIDTH SPACE (ZWSP) character, U+200B, after the character. In HTML markup, you can use the character reference `', e.g.
MyProject\Sub\Level
If you add the characters via scripting, you can enter the character itself, using the string literal \u200b.
Some old browsers (IE 6) used to have problems with this, but now this approach seems to work better than the alternative, the old <wbr> tag (which was well-supported but has now been messed up in new versions of IE).
Use the following css in the element that contains the text:
word-wrap: break-word;
It's a css3 property supported in modern browsers: Google Chrome 6, Internet Explorer 8, Firefox 3, Opera 10 y Safari 5.
Acclaration: It won't break on / character only, it could break on any character of the word according to the stretching of container.
One option is to use the soft-hyphen () around the \ characters; the soft-hyphen allows a word to break at a given point, appearing only if the word does, in fact, break at that point.
It also doesn't appear in the text if it's copied and pasted (tested in Chromium 19/Ubuntu 11.04); this approach uses replace() and jQuery's html() method with the following HTML:
<ul>
<li>\some\text\possibly\a\path</li>
<li>\another\path</li>
<li>\something\else\also\quite\long</li>
</ul>
And CSS:
li {
width: 8em;
border: 1px solid #000;
}
jQuery:
$('li').html(function(i, h) {
return h.replace(/(\\)/g, '$1')
});
JS Fiddle demo.
Obviously, you don't need to use the soft-hyphen on both sides of the \ character, that was just a demonstration for how it might be used.
An alternative, if you'd rather avoid the appearance of - characters at the break-point, is to use the same approach as above, but instead insert an empty span element, and give it the style display: inline-block;:
jQuery:
$('li').html(function(i, h) {
return h.replace(/(\\)/g, '$1<span></span>')
});
CSS:
li {
width: 8em;
border: 1px solid #000;
}
li span {
display: inline-block;
}
JS Fiddle demo.
References:
html().
replace().
You could probably follow the example on jQuery - Find and replace text, after body was loaded and have it insert a break following every slash
I'm working on adding line number support to Rainbow, a syntax highlighter, but I can't figure out how to make the line numbers uncopyable.
Disabling selection via user-select: none; makes an element unhighlightable, but you can still copy its text by highlighting around it and then copying, which ends up copying the line numbers along with code.
Here is a working example of the problem: http://jsfiddle.net/CjJLv/8/
Any help would be appreciated. Thanks!
Okay, the easiest way in compliant browsers, and, sadly, not reliable cross-browser, is to use generated content (I've removed the various parts where index was being added to textual content in the plug-in, and used the following (at the end of the CSS) to implement un-copyable text:
table.rainbow {
counter-reset: line;
}
table.rainbow tbody tr td:first-child {
counter-increment: line;
}
table.rainbow tr td:first-child::before {
content: counter(line);
}
JS Fiddle demo.
This does, though, have some rather large flaws (the cross-browser unfriendly approach being the biggest), so I'll try for something better...
I would just add a regular list.
if (window.Rainbow) window.Rainbow.linecount = (function(Rainbow) {
Rainbow.onHighlight(function(block) {
var lines = $(block).text().split('\n');
var $lines = $('<ul class="lines"/>');
for (var i = 0, len = lines.length; i < len; i++) {
$lines.append('<li class="line"'+ i +'>'+ i +'</li>');
}
$(block).before($lines);
});
})(window.Rainbow);
And CSS:
.lines {
float: left;
padding-right: 1.5em;
padding-left: .5em;
}
So now you can select just the code if you highlight carefully.
Demo: http://jsfiddle.net/elclanrs/CjJLv/18/
David Thomas's answer is perfect for line numbers. More generally, if you have other text you don't want to be copied, you can have it as generated content:
<style>#uniqueid::before { content: 'TEXT GOES HERE'; }</style>
<span id="uniqueid"></span>
But it's ugly to have to embed text in your CSS, so you can refine this using CSS attr() to read the text from an attribute in the HTML (as suggested by pimvdb):
<style>[data-nocopy]::before { content: attr(data-nocopy); }</style>
<span data-nocopy="TEXT GOES HERE"></span>
<span data-nocopy="AND HERE"></span>
Demo: http://jsbin.com/fob/1/edit
This works in Firefox, Safari, and Chrome due to 21-year-old(!) bugs in selecting generated content:
https://bugzilla.mozilla.org/show_bug.cgi?id=12460
https://bugs.webkit.org/show_bug.cgi?id=7562
https://bugs.chromium.org/p/chromium/issues/detail?id=80466
But in old IE (< 8) the text will be completely invisible; in newer IE it should be visible but may well be copyable. In general don't use this technique for anything critical, as these bugs might get fixed one day...
And use sparingly, as this can be very user-hostile.
You could display each line number as a sequence of <img>s.
Here's the thing. I use 'Highlight.js' (a javascript-based automatic syntax highlighter) to syntax-highlight code on my website. But it doesn't support line numbers or zebra-striping (for alternate lines of code).
My code block is wrapped in <pre><code> blocks like this:
<pre><code>
<script type="text/javascript">
// Say hello world until the user starts questioning
// the meaningfulness of their existence.
function helloWorld(world) {
for (var i = 42; --i >= 0;) {
alert('Hello ' + String(world));
}
}
</script>
<style>
p { color: pink }
b { color: blue }
u { color: "umber" }
</style>
</code></pre>
And the output looks like this:
Now I want to show line numbers for the code block dynamically using JavaScript. How do I do that? (Also, if possible, how do I show zebra-striping?)
Thanks.
PS: I don't know JavaScript, so please try to be as clear as possible. I will try my best to understand. Thanks.
You could use an alternate framework such as http://alexgorbatchev.com/SyntaxHighlighter/
Or take a look here and find something that suites.
http://www.1stwebdesigner.com/css/16-free-javascript-code-syntax-highlighters-for-better-programming/
The basic steps would be:
Take the HTML inside the element.
Split by newline characters (\n).
For each string, add a number and a dot in front of it.
Combine the strings again with newline characters.
Set the string as the HTML of the element.
However, this would mess up the syntax highlighting of the syntax highlighter because it most likely won't recognize that the code has line numbers in front. So the syntax highlighter needs to provide the functionality of line numbers for you.
Adding a new answer to an old question.
I wanted to display line numbers in the left margin the way ace.js does.
My solution has some hacky details, but I wanted to share it anyway, because it turns out that absolute-positioned spans within relative-positioned spans work pretty well for this.
Encouraged by the above answers and this answer about relative positioning without taking up space, I used:
var line = 1;
code = code.replace(/^/gm, function() {
return '<span class="line-number-position"><span class="line-number">' + line++ + '</span></span>';
});
The regular expression /^/gm "replaces" the beginning of each line with the span-within-span.
is a zero-width space, because apparently firefox seems to have trouble deciding whether to put a zero-height span at the top or the bottom of the character.
line-number-position and line-number are CSS classes like these:
.line-number-position {
position: relative;
top: 0;
}
.line-number {
position: absolute;
text-align: right;
right: 17px;
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace;
font-size: 12px;
}
Yes, there are some magic numbers in there to match ace formatting, but the point is to put a relative-positioned zero-sized span at the beginning of each line and use it as a reference point to add an absolute-positioned span out in the left margin.
Works on current Chrome, Safari, Firefox, and Opera.
I'm looking for a way to disable the copying of a specific area of text when you use Ctrl + C, etc. Whether I have to write the text a different way or not.
http://gyazo.com/721a0a5b5af173beb1ad3305633beafb.png
Above is what this is for. It's a syntax highlighter I have been working on (3 languages supported so far). When the user selects ANY text in any way, I don't want the line numbers to be copied.
I can't think of a way to display line numbers, without them actually being there.
As long as the line numbers and the source code are mixed together, this is going to be tough to prevent programmatically, if not impossible.
The ideal way would be having the source code in an actual container of its own.
Open a document inspector and look at how Github do it, for example: https://github.com/jbrisbin/riak-exchange/blob/master/Makefile
they have a separate <pre> element containing the line numbers, and a <table> cell containing the code. (I assume selecting is a reason why they use tables here, but I do not know for sure.)
Give this a try...
Demo: http://jsfiddle.net/wdm954/UD8Dq/7
I layered the div so the code div is on top and the numbers are behind. When you copy and paste you should just get the code.
.lines {
position: absolute;
width: 80%;
color: #666;
}
.lines pre:nth-child(odd) {
background-color: #EEE;
}
.code {
position: absolute;
z-index: 2;
padding-left: 5%;
width: 80%;
}
<div class="box">
<div class="lines">
<pre>1</pre>
<pre>2</pre>
<pre>3</pre>
<pre>4</pre>
</div>
<div class="code">
<pre>
code
code
code
code
</pre>
</div>
</div>
Setting user-select, -moz-user-select, and -webkit-user-select to none might work. For IE, you will need to handle onselectstart and return false.
This will prevent people from selecting the text, but I don't know what happens when it's beside other text that you attempt to copy.
I know that this question is three years old, but with HTML5 you can store line numbers in a data attributes and use CSS2 to display the text. This should prevent line numbers from being copied.
HTML
<span data-line-number='1' class='line'></span>
CSS
.line:before {
content: attr(data-line-number);
}