Not sure if anyone has come across this. I'm using PrismJS syntax highlighter to highlight code. Application is written in Reactjs and what I'm trying to do is inside a WYSIWYG editor I'm wrapping user selected text with pre + code when user wants to insert code block. PrismJS seems to tokenize elements correctly as you would expect:
But as you can probably see from the image above, everything is put into a single line. Rather then nice code block:
I'm not sure what's wrong, using css from prismjs site:
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection,
pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection,
code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection,
pre[class*="language-"] ::selection,
code[class*="language-"]::selection,
code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
#media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre) > code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}
/* Inline code */
:not(pre) > code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
background: hsla(0, 0%, 100%, .5);
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #dd4a68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}
Here is outputted html:
EDIT:
If adding word-wrap: pre-wrap this is the outcome:
I had a similar issue when initializing the element manually. I stumbled upon this discussion, which had a fix that worked for me: https://github.com/PrismJS/prism/issues/1764
HTML - Load script with flag data-manual:
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/prism.min.js" data-manual></script>
JS - Add the following hook:
Prism.hooks.add("before-highlight", function (env) {
env.code = env.element.innerText;
});
Prism.highlightElement(code);
Working example:
https://codepen.io/Ukmasmu/pen/xxZLwxG?editors=1010
Try to update the CSS file with:
white-space: pre-wrap
https://github.com/PrismJS/prism/issues/1237
In case this is helpful for anyone else, I have a textarea that updates a code block as you type, and this worked for me:
<textarea onkeyup="this.onchange();" onchange="document.getElementById('query-highlighted').textContent = this.value; Prism.highlightAll();"></textarea>
<pre><code class="language-sql" id="query-highlighted"></code></pre>
Namely, I used .textContent = instead of .innerText = (the latter didn't preserve the line breaks as expected).
I was aided by Sever van Snugg's answer and the issue he linked.
1. Activate normalize whitespace plugin
I suggest you activate normalize whitespace plugin and set the break-lines property instead of manipulating prism.css file to using white-space: pre-wrap like this:
Prism.plugins.NormalizeWhitespace.setDefaults({
'remove-trailing': true,
'remove-indent': true,
'left-trim': true,
'right-trim': true,
'break-lines': 60, //max number of characters in each line before break
});
I'm using the above approach in my blog, and it works like a charm. You can adjust the break-lines value according to your preferences of course.
2. Insert a line break tag <br> to break a line at will
Now that you set the break-line property after a certain maximum number of characters, you probably want to break some lines at will for cleaner code. To do so you need to insert a <br> tag where you want to have a break line.
NOTE: if you're using an html parser to parse dynamic content with prism
If you're using a parser to parse you dynamically generated html code as a string (from a database for example) and prims is not parsing your <br> tags you'll have to use before-sanity-check prism hook like this:
Prism.hooks.add('before-sanity-check', function (env) {
env.element.innerHTML = env.element.innerHTML.replace(/<br>/g, '\n');
env.code = env.element.textContent;
});
before highlighting, what the above code does is replacing <br> tags with \n since prism can't parse <br> as a line break.
Similar to the answer by Sever van Snugg, I use the following solution where the forEach loop highlights all the code nodes according to the style rules of the Prism CSS stylesheet used (because I have several code tags on a single page). I locate these scripts in the bottom of my HTML body:
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.27.0/prism.min.js" data-manual></script>
<script>
Prism.hooks.add("before-highlight", function (env) {
env.code = env.element.innerText;
});
code = document.getElementsByTagName('code');
Array.from(code).forEach(el => { Prism.highlightElement(el) });
</script>
I tried to mixed Markdown and Prismjs the trick is to replace '\n' with '\r\n' to keep breaklines.
from bs4 import BeautifulSoup
...
code_tag = soup.new_tag('code class="lang-%s"' % lang)
code_tag.string = code.string.replace('\n','\r\n')
code.replaceWith(code_tag)
Related
I would like to achieve the following with my code:
Issue (a) Change only Click Here to be surrounded by a box.
Issue (b) The border for the box in (a) should disappear and reappear.
Currently, I face the following issues with my code:
Issue (a)
For (a), my code does not just change Click Here to be surrounded by a box. It also changes Pinterest to be surrounded by a box. I believe the issue is with selecting the top level ul but I have not succeeded in doing so.
Relevant CSS code
.cover-buttons ul:first-of-type li:nth-last-child(5) a {
color: black;
border: 1px solid black;
padding: 14px 18px!important;
font-weight: 400;
line-height: 17px;
font-size: 12px;
display: inline-block;
transition: all .2s ease;
overflow: hidden;
border-radius: 2px;
box-sizing: border-box;
list-style-type: none;
font-family: 'Varela Round', 'Poppins', sans-serif;
}
Issue (b)
For (b), I can't seem to get the box border to blink.
Relevant Javascript code
$(function(){
var count = 0, $input = jQuery('.buttons.medium.button-outlined').not('.add-review, .bookmark, .show-dropdown, .sn-share'), interval = setInterval(function() {
if ($input.hasClass('blur')) {
$input.removeClass('blur').addClass('focus'); ++count;
} else {
$input.removeClass('focus').addClass('blur');
}
if (count === 3) { clearInterval(interval); }
}, 2000);
});
Relevant CSS code
.focus {
border: 1px solid white;
}
.blur {
border: 1px solid black;
}
The strange thing about issue (b) is that it seems to work when I change the background-color as shown here: https://jsfiddle.net/75nvLs4x/12/. However, when I try to modify the border thickness it does not work.
Full script including HTML is included here: https://jsfiddle.net/75nvLs4x/14/
Thank you for your help.
Issue A
Your selector is: .cover-buttons ul li:nth-last-child(5) a this will affect any ul inside .cover-buttons. As there are two uls that have li:nth-last-child(5), both have the li:nth-last-child applied.
You can fix this by saying only the ul that's directly inside .cover-buttons and only the li directly inside that ul
.cover-buttons > ul > li:nth-last-child(5) a
Issue B
Your border issue is due to specificity - the border in the .cover-buttons ul li:nth-last-child(5) a section is more specific than just .focus so is always used. You could add !important to the border inside .focus, but that's not best practice - instead, remove the border from the main block and it works fine.
Updated fiddle: https://jsfiddle.net/75nvLs4x/18/
I have a below code where I am trying to increase or decrease the font size of text. If JavaScript is disabled in my browser, I am not able to increase or decrease the size of the text. Is there any way to do without JavaScript as my browser does use JavaScript for security reasons. Any suggestions will be really helpful.
JSFIDDLE
<html>
<head>
<style type="text/css">
.Small{ font: 12px Times New Roman, Arial, Sans-Serif; }
.Medium{ font: 15px Times New Roman, Arial, Sans-Serif; }
.Large{ font: 18px Times New Roman, Arial, Sans-Serif; }
</style>
<script language="JavaScript">
function changeFont(styleSheet)
{
document.getElementById('textArea').className=styleSheet;
}
</script>
<noscript>Your browser does not support JavaScript!</noscript>
</head>
<body>
<span class="Small" id="textArea">Test which will change size</span>
<br><br><br>
Small
Medium
Large
</body>
</html>
I think someone mentioned about this, Javascript should be runnable for most of the cases so don't worry about it, although CSS hack is fun but sometimes not really useful in terms of readability, reliability and compatibility.
html, body { font-family: "Arial"; }
.content { font-size: 10px; }
.small:checked ~ .content { font-size: 10px; }
.medium:checked ~ .content { font-size: 20px; }
.large:checked ~ .content { font-size: 30px; }
<input class="small" name="font-radio" type="radio" checked="checked"/>
<input class="medium" name="font-radio" type="radio"/>
<input class="large" name="font-radio" type="radio"/>
<div class="content">I can change fontsize without Javascript!</div>
There are no good ways.
You could do a really horrible hack involving checkboxes, the :checked pseudo-class, the general sibling combinator and some non-semantic markup … which would also massively constrain your design options.
Browsers come with built-in tools for adjusting the size of content. Focus on creating a fluid, responsive design instead. Let sizing issues be handled with the built-in zooming features of the browsers.
As a general statement, once the page has been rendered and DOM was built, you can't change it without JavaScript. That's what JavaScript is supposed to do and that's what you are supposed to use.
As another general statement, "my browser does not use JavaScript for security reasons", in most cases, simply shows lack of proper understanding of how web works today and, for the most part, it is plain wrong.
In other words, today, no pages, including payment portals, do not disable JavaScript and, when properly coded, JavaScript is safe.
However, you could do this using CSS by, for example, (un)checking/selecting hidden checkboxes/radio buttons and having elements styled differently after a :checked or :not(:checked) element.
Here's a simple example:
.content {
font-size: 1.2rem;
}
#font-size-medium:checked ~ .content {
font-size: 1.8rem;
}
#font-size-large:checked ~ .content {
font-size: 2.7rem;
}
/* the rest is just styling, can be ignored for the purpose of the exercise */
#font-size-small:checked ~ [for="font-size-small"],
#font-size-medium:checked ~ [for="font-size-medium"],
#font-size-large:checked ~ [for="font-size-large"] {
background-color: #f5f5f5;
color: black;
}
[for^="font-size"] {
padding: .5rem 1rem;
border: 1px solid #ddd;
display: inline-block;
margin: 0 .5rem 1rem 0;
cursor:pointer;
color: #999;
}
[for^="font-size"]:hover {
background-color: #f5f5f5;
}
[name="font-size-change"] {
position: absolute;
z-index: -1;
visibility: hidden;
}
<input type="radio" id="font-size-small" name="font-size-change" checked>
<input type="radio" id="font-size-medium" name="font-size-change">
<input type="radio" id="font-size-large" name="font-size-change">
<label for="font-size-small">Small</label>
<label for="font-size-medium">Medium</label>
<label for="font-size-large">Large</label>
<div class="content">
Put the text you want changed here...
</div>
But please note this change in rendering happens without changing anything in DOM. The elements remain the same, you're only changing what CSS rules apply to them, by (un)checking <input>s.
I have a variable which has two classes. I am wanting to remove the small class before the html() pushes the div to DOM.
As of right now, the div is rendering with the small class. I am wanting that to be removed.
I have tried switching the order of the removeClass to place it before the html(), but that didn't work.
$('#review').removeClass('small').html(prev);
Does anyone know how I can do this?
var prev = "<div class='big small'>Hello</div>";
$('#review').html(prev).removeClass('small');
.big {
color: red;
font-size: 2rem;
}
.small {
color: blue;
font-size: 1.1rem;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="review"></div>
UPDATE
I tried to make my question really basic for simplicity, but it turns out, the array I had in my actual code made this more complex.
$('body').on('change', '.option-check', function() {
var calSelectionImg = [];
$('.calendar-check:checked').each(function() {
calSelectionImg.push($(this).data('calendar-img'));
});
$('#pg-img-review').html(calSelectionImg);
});
.cal-selected-img {
color: red;
font-size: 2rem;
}
.small {
color: blue;
font-size: 1.1rem;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="checkbox" class="option-check" data-cal-choice="<div class='cal-selected-img small'>Hello</div>">
<input type="checkbox" class="option-check" data-cal-choice="<div class='cal-selected-img small'>Goodbye</div>">
<div id="pg-img-review" class="margin15"></div>
You're modifying #review, not your new code. So, I added appendTo. It's a minor restructure, but it fixes the issues with minimal complications.
var prev = "<div class='big small'>Hello</div>";
$(prev).removeClass('small').appendTo("#review");
.big {
color: red;
font-size: 2rem;
}
.small {
color: blue;
font-size: 1.1rem;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="review"></div>
In the example you've given, the HTML in prev is just a string. You need to parse it into a DOM object before you can call a function such as .removeClass() on it.
jQuery provides a number of options for parsing HTML elements, but as a vanilla JS over jQuery proponent, I often favour this particular approach:
var tempDiv = document.createElement('div');
tempDiv.innerHtml = "<p class='small'>The string of HTML</p>";
var parsedElement = tempDiv.firstChild;
I can then call the jQuery method parsedElement.removeClass("small") or Vanilla JS parsedElement.classList.remove("small") to successfully remove the class.
var prev = "<div class='big small'>Hello</div>";
$('#review').html(prev).find('.small').removeClass('small');
.big {
color: red;
font-size: 2rem;
}
.small {
color: blue;
font-size: 1.1rem;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="review"></div>
You may need this:
var prev = "<div class='big small'>Hello</div>";
$('#review').html(prev);
$(".big").removeClass('small');
Add your DIV first, and then remove the class you don't need later.
Don't worry
$(".big").removeClass('small');
would cause any problem. If there is no CLASS [small], the DOM will ignore the js.
That's all.O(∩_∩)O~
I am trying to get the pre tag to break on the line breaks like how I have it displayed. Instead its putting the vv section on the first, not breaking in the middle of the comments comment section, etc. Is there some CSS for this that might be helpful?
.testingZone {
margin-left: 20px;
}
.testingZone a {
color: blue;
}
.testingZone a:hover {
color: gold;
}
.testingZone pre {
font-family: monospace;
white-space: normal;
}
<div class="testingZone">
<pre>
<!-- Note: comment comment comment.
Comment Comment/Comment, more comments "comment"-->
<vv:aaa vv:bbb="sss" vv:ccc="SectionA;SectionB;SectionC=SectionD;SectionE=SectionF.SectionG.SectionH;,SectionI=SectionJ;SectionK=SectionL;SectionM=SectionN;SectionO=SectionP.SectionQ.SectionR;SectionS=/;"/>
<vv:aaa vv:bbb="iii" vv:ccc="\SectionT\SectionU\_SectionV,\SectionW\SectionX,\SectionY\_SectionZ"/>
</pre>
</div>
Instead of white-space: normal;, use white-space: pre-line;. This allows runs of white-space to be combined within a line, but doesn't allow lines to be merged. This will merge all the leading spaces on each line into a single space.
.testingZone {
margin-left: 20px;
}
.testingZone pre {
font-family: monospace;
white-space: pre-line;
}
<div class="testingZone">
<pre>
<!-- Note: comment comment comment.
Comment Comment/Comment, more comments "comment"-->
<vv:aaa vv:bbb="sss" vv:ccc="SectionA;SectionB;SectionC=SectionD;SectionE=SectionF.SectionG.SectionH;,SectionI=SectionJ;SectionK=SectionL;SectionM=SectionN;SectionO=SectionP.SectionQ.SectionR;SectionS=/;"/>
<vv:aaa vv:bbb="iii" vv:ccc="\SectionT\SectionU\_SectionV,\SectionW\SectionX,\SectionY\_SectionZ"/>
</pre>
</div>
There's no way to totally ignore all the white-space at the beginning of each line. See MDN for descriptions of all the white-space styles.
You need to remove the white-space rule on the .testingZone pre tag or set it to the default for <pre> tags, which is 'pre'.
So basically: Change
.testingZone pre {
font-family: monospace;
white-space: normal;
}
to
.testingZone pre {
font-family: monospace;
}
or to
.testingZone pre {
font-family: monospace;
white-space: pre;
}
I am getting some external html page where all the data is coming in lowercase. with css, i tried to capitalize the first intial of the complete label tag but i am unable to do it, it makes complete uppercase like this:
.fontmodal {
text-transform:capitalize !important;
}
but that did not worked...
<table><fieldset><div><label>DATA</label></div></fieldset></table> - This is the current Structure
Now i am trying to same in jquery, i am not sure what and how to proceed.
Here is my code what i am trying:
$('#Container2').find("table>label").css(textTransform,'capitalize');
See below:
label {
text-transform: lowercase;
}
div::first-letter {
text-transform: uppercase;
}
<table>
<fieldset>
<div>
<label>DATA</label>
</div>
</fieldset>
</table>
If you can't change the HTML and need to apply the capital letter on the first letter, you need to change the default display property of the <label> tag :
:first-letter :
has only an effect on elements with a display value of block,
inline-block, table-cell, list-item or table-caption. In all other
cases, ::first-letter has no effect. (source MDN)
label {
display: inline-block;
text-transform: lowercase;
}
label::first-letter {
text-transform: capitalize;
}
<table>
<fieldset>
<div>
<label>DATA</label>
</div>
</fieldset>
</table>
You simplify it and do something like below.
$(document ).ready(function() {
$("label").addClass("capitalizer"); // Adjust specificity as needed
});
.capitalizer {
font-weight: bold;
font-size: 72px;
display: inline-block;
color: red;
}
.capitalizer::first-letter {
text-transform: capitalize;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<label>data</label>
</div>
Note: I prefer .addClass because .CSS adds inline css to your HTML and that's not advisable.
You can achieve this using the CSSS selector :first-letter.
The subtly I have found is that it doesn't appear to be supported on the <label/> tag (didn't work in my demo code, anyhow)
But we can get round that:
label {
text-transform: lowercase;
}
div:first-child:first-letter {
text-transform: uppercase;
color: red;
}
DEMO: http://jsfiddle.net/30trmm3w/1
I don't get what's wrong a simple CSS rule should do the trick :
#Container2 label {
text-transform: capitalize;
}