-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The Lines plugin: control your lines via CSS #2389
Open
galaxy4public
wants to merge
8
commits into
PrismJS:master
Choose a base branch
from
galaxy4public:plugin-lines
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
9b152c3
The Lines plugin: control your lines with CSS
galaxy4public 4e7197f
Merge branch 'master' of https://github.com/PrismJS/prism into plugin…
galaxy4public a49ff52
made class selectors a bit more specific
galaxy4public 89486e0
Reworked to actually parse the content
galaxy4public d7e2f7b
Reworked to actually parse the content
galaxy4public bc48522
Removed unnecessary safety sensor.
galaxy4public 485e027
Forgot to run "gulp" :(
galaxy4public 4c05ae6
Removed erroneous check that was resulting in one-liner raw text bloc…
galaxy4public File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,272 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
|
||
<meta charset="utf-8" /> | ||
<link rel="icon" href="favicon.png" /> | ||
<title>Line Numbers ▲ Prism plugins</title> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wrong title. |
||
<base href="../.." /> | ||
<link rel="stylesheet" href="style.css" /> | ||
<link rel="stylesheet" href="themes/prism.css" data-noprefix /> | ||
<link rel="stylesheet" href="plugins/lines/prism-lines.css" data-noprefix /> | ||
<script src="scripts/prefixfree.min.js"></script> | ||
|
||
<script>var _gaq = [['_setAccount', 'UA-33746269-1'], ['_trackPageview']];</script> | ||
<script src="https://www.google-analytics.com/ga.js" async></script> | ||
</head> | ||
<body> | ||
|
||
<header data-plugin-header="lines"></header> | ||
|
||
<section class="language-markup"> | ||
<h1>How to use</h1> | ||
|
||
<p>This plugin is designed to work only for code blocks (<code><pre><code></code>) and not for inline code.</p> | ||
<p>The primary functionality of the plugin does not require any configuration or additional classes or attributes, however to get the most of it you will need to provide additional CSS rules to dress things up.</p> | ||
<p>To keep the plugin as non-intrusive as possible the only extra CSS rules that are provided with the plugin are to introduce a wrapped line marker on the left side of the code block. See <a href="plugins/lines/index.html#examples">Examples</a> on how disable this or change its behaviour. | ||
<p>This plugin wraps each physical line of the multi-line code block with <code><div class="line"><a></a>...</div></code>, which allows to style the result quite extensively using only CSS.</p> | ||
<p>The stylesheet provided with the plugin uses one pseudo-element (<code>div.line::after</code>) to display a visual marker for the wrapped lines. The examples below are also leveraging another pseudo element (<code>div.line > a::before</code>), which leaves two more pseudo-elements for you to style.</p> | ||
<p>Using just this plugin one can mimic the Line Numbers plugin output by adding the <code>line-numbers</code> class to your desired <code><pre></code> or any of its ancestors, and by updating your CSS rules to include something along the following lines: | ||
<style> | ||
/* Visually backward compatible replacement of the line-numbers plugin :) */ | ||
.line-numbers pre[class*="language-"], | ||
pre[class*="language-"].line-numbers { | ||
counter-reset: linenumber; | ||
counter-reset: linenumber var(--counter-start,0); | ||
padding-left: 0; | ||
} | ||
|
||
pre[class*="language-"] > code { | ||
white-space: inherit; | ||
} | ||
|
||
.line-numbers pre[class*="language-"] > code, | ||
pre[class*="language-"].line-numbers > code { | ||
padding-left: 3.8em; | ||
} | ||
|
||
.line-numbers pre[class*="language-"] div.line > a::before, | ||
pre[class*="language-"].line-numbers div.line > a::before { | ||
content: counter(linenumber); | ||
box-sizing: border-box; | ||
counter-increment: linenumber; | ||
color: #999; | ||
text-indent: 0; | ||
text-align: right; | ||
left: -3.8em; | ||
display: block; | ||
position: absolute; | ||
width: 3em; | ||
height: 100%; | ||
padding-right: .8em; | ||
border-right: solid #999; | ||
cursor: default; | ||
pointer-events: none; | ||
} | ||
</style> | ||
<pre id="line-numbers-css" class="line-numbers" style="white-space:pre-wrap;max-width:75%;margin-bottom:1em;"><code class="language-css">/* Visually backward compatible replacement of the line-numbers plugin :) */ | ||
.line-numbers pre[class*="language-"], | ||
pre[class*="language-"].line-numbers { | ||
counter-reset: linenumber; | ||
counter-reset: linenumber var(--counter-start,0); | ||
padding-left: 0; | ||
} | ||
|
||
.line-numbers pre[class*="language-"] > code, | ||
pre[class*="language-"].line-numbers > code { | ||
padding-left: 3.8em; | ||
} | ||
|
||
.line-numbers pre[class*="language-"] div.line > a::before, | ||
pre[class*="language-"].line-numbers div.line > a::before { | ||
content: counter(linenumber); | ||
counter-increment: linenumber; | ||
color: #999; | ||
text-indent: 0; | ||
text-align: right; | ||
box-sizing: border-box; | ||
left: -3.8em; /* make it -4.6em if your box-sizing is content-box */ | ||
display: block; | ||
position: absolute; | ||
width: 3em; | ||
height: 100%; | ||
padding-right: 0.8em; | ||
border-right: solid #999; | ||
}</code></pre></p> | ||
<p>... and the browser will take care of the rest. To give all code blocks line numbers, add the <code>line-numbers</code> class to the <code><body></code> of the page.</p> | ||
<p>Optional: You can specify the <code>data-start</code> (Number) attribute on the <code><pre></code> element. It will shift the line counter (if you are using the above CSS example).</p> | ||
<p>Optional: To support multiline line numbers using soft wrap, apply the CSS <code>white-space: pre-line;</code> or <code>white-space: pre-wrap;</code> to your desired <code><pre></code>.</p> | ||
<p>Optional: There is a rudimentary support for line highlighting and active line numbers, please see the corresponding examples below. | ||
</section> | ||
|
||
<section class="lines"> | ||
<h1>Examples</h1> | ||
|
||
<h2>JavaScript</h2> | ||
<p>Please note that this <code class="language-markup"><pre></code> does not have the <code>line-numbers</code> class but its parent does.</p> | ||
<div class="line-numbers"> | ||
<pre class="lines" data-src="plugins/lines/prism-lines.js" style="white-space:pre-wrap;"></pre> </div> | ||
|
||
<h2>CSS</h2> | ||
<p>Please note the <code>data-start="-5"</code> in the code below.</p> | ||
<pre class="line-numbers" data-src="plugins/lines/prism-lines.css" data-start="-5"></pre> | ||
|
||
<h2>HTML</h2> | ||
<p>Please note the <code>style="white-space:pre-wrap;"</code> in the code below and how it affects the wrapped lines.</p> | ||
<pre class="line-numbers" data-src="plugins/lines/index.html" style="white-space:pre-wrap;"></pre> | ||
|
||
<h2>Unknown languages</h2> | ||
<p>Please note the how the following style: | ||
<pre><code class="language-css">#demo1 div.line:nth-of-type(3) { | ||
background: yellow; | ||
}</code></pre> can be used to highlight a line.</p> | ||
<style> | ||
#demo1 div.line:nth-of-type(3) { | ||
background: yellow; | ||
} | ||
</style> | ||
<pre id="demo1" class="language-none" style="white-space:pre-wrap;"><code>This raw text | ||
is not highlighted | ||
but it still has | ||
lines wrapped in <div>s, so we could benefit from the support this plugin provides such as nice visual line wrapping and the ability to select lines using CSS rules. | ||
|
||
The long and the following blank lines are here to demonstrate the wrapping of the long line.</code></pre> | ||
<p>A similar example but without Lines support (please note how plugin was selectively disabled for a particular block using the <code>nolines</code> class:</p> | ||
<pre class="language-none nolines" style="white-space:pre-wrap;"><code>This raw text | ||
is not highlighted | ||
and it was explicitly | ||
excluded from being processed through the Lines plugin. The rendering of this block is exactly the same as if no Lines plugin was present. You may notice that the wrapping still happens due to the associated CSS class, though, yet it is hard to understand which line was wrapped and which was not. | ||
|
||
The long and the following blank lines are here to demonstrate the wrapping of the long line.</code></pre> | ||
|
||
<h2>Line wrap indicator</h2> | ||
<p>The location and presentation of the line wrap indicator can be easily customised by adjusting the <code>div.line::after</code> pseudo-element using CSS. For example, to relocate the indicator to the right side one could come up with something similar to the following stylesheet:</p> | ||
<pre class="language-css"><code>pre[class*="language-"] div.line { | ||
padding-left: 0; | ||
text-indent: 0; | ||
} | ||
|
||
pre[class*="language-"] div.line::after { | ||
right: -1em; | ||
bottom: 0; | ||
left: auto; | ||
top: auto; | ||
width: 1.5em; | ||
transform: none; | ||
}</code></pre> | ||
<p>The result of the applying the above style to a code block can be observed below:</p> | ||
<style> | ||
#demo2 div.line { | ||
padding-left: 0; | ||
text-indent: 0; | ||
} | ||
#demo2 div.line::after { | ||
right: -1em; | ||
bottom: 0; | ||
left: auto; | ||
top: auto; | ||
width: 1.5em; | ||
transform: none; | ||
} | ||
</style> | ||
<pre id="demo2" class="language-none" style="white-space:pre-wrap;"><code>This raw text | ||
has a very long line to demonstrate the relocation of the line wrapping indicator from the default left side to the right side of the block. It is just showcases what is possible when you have semantic representation of lines inside your <pre> blocks. | ||
|
||
The empty line above is there for the demonstration purposes.</code></pre> | ||
|
||
<p>The indicator can be completely disabled by setting the <code>display: none</code> CSS property for the <code>div.line::after</code> pseudo-element, e.g. with the following stylesheet:</p> | ||
<pre class="language-css"><code>pre[class*="language-"] div.line::after { | ||
display: none; | ||
} | ||
|
||
pre[class*="language-"] div.line { | ||
padding-left: 0; | ||
text-indent: 0; | ||
} | ||
|
||
#demo3 div.line:nth-of-type(2) { | ||
background: yellow; | ||
}</code></pre> | ||
<p>To demonstrate that the Lines plugin still did its work the highlighting of the second line was added to the above stylesheet. The resulting rendering of a block looks as follows: | ||
<style> | ||
#demo3 div.line::after { | ||
display: none; | ||
} | ||
|
||
#demo3 div.line { | ||
padding-left: 0; | ||
text-indent: 0; | ||
} | ||
|
||
#demo3 div.line:nth-of-type(2) { | ||
background: yellow; | ||
} | ||
</style> | ||
<pre id="demo3" class="language-none" style="white-space:pre-wrap;"><code>This raw text | ||
demonstrates that the line wrapping indicator can be completely disabled and you will get the same experience as like no Lines plugin was there. | ||
|
||
However, as you can see above, the lines are still semantically represented and are addressable using CSS.</code></pre> | ||
|
||
<h2>Active line numbers</h2> | ||
<p>There is a basic support for active line numbers, i.e. when the user clicks on the line number (if the line numbers are displayed) and the location bar is updated with the hash fragment corresponding to the line clicked.</p> | ||
<p>The Lines plugin provides bare minimum to support the active line numbers, the user still need to do some preparation work. Following are conditions for working with the active line numbers in the Lines plugin: | ||
<ol> | ||
<li>the active line numbers functionality is conditional on the presence of the <code>id</code> attribute of the enclosing <code><pre></code> element;</li> | ||
<li>when lines are wrapped with <code><div><a>...</div></a></code> each <code><div></code> is assigned an <code>id</code> which is a composition of <code><pre></code>'s <code>id</code> and the corresponding line number joined by <code>.</code>;</li> | ||
<li>The user needs to provide the corresponding styles to make line numbers interactive.</li> | ||
</ol></p> | ||
<p>This means that without any additional configuration the Lines plugin provides a rudimentary support for linking lines and code blocks (e.g. this mimics what the Line Highlight plugin does with the <code>linkable-line-numbers</code> option)</p> | ||
<p>However, the problem with that approach is that when somebody is following such a URL that points to a very deeply burrowed code block on a large page, chances are that PrismJS won't be able to modify the DOM tree in time to let the browser "see" the target.</p> | ||
<p>One way of addressing the issue would be to pre-generate the structure inside the codeblock, so it is stable from the browser perspective, i.e. wrap all physical lines with <code><div><a></code> as the Lines plugin does and ensure that the <code>id</code>s are properly assigned to the <code><div</code>s. | ||
<p>Below is a non-working(*) demonstration of the active line numbers functionality, it uses the <a href="plugins/lines/index.html#line-numbers-css">example stylesheet</a> that was presented at the start of this page. You still can reference a line using a fragment (e.g. clicking <a href="plugins/lines/index.html#demo4.3">this will point you to line 3</a>), but since the page is using <code><base href="../.." /></code> one can forget of using fragments without page reloads.</p> | ||
<p>The following style rules were added to make the experience a bit more pleasant:</p> | ||
<pre class="language-css" style="white-space:pre-wrap;"><code>.line-numbers pre[class*="language-"][id] div.line > a::before, | ||
pre[class*="language-"][id].line-numbers div.line > a::before { | ||
cursor: pointer; | ||
pointer-events: auto; | ||
} | ||
|
||
.line-numbers pre[class*="language-"][id] div.line > a:hover::before, | ||
pre[class*="language-"][id].line-numbers div.line > a:hover::before { | ||
color: black; | ||
background: rgba(0,0,0,.1); | ||
} | ||
|
||
/* add visual assist for demo purposes */ | ||
#demo4 *:target { | ||
background-color: #0000ff24; | ||
}</code></pre> | ||
<style> | ||
#demo4 div.line > a::before { | ||
cursor: pointer; | ||
pointer-events: auto; | ||
} | ||
|
||
#demo4 div.line > a:hover::before { | ||
color: black; | ||
background: rgba(0,0,0,.1); | ||
} | ||
|
||
#demo4 *:target { | ||
background-color: #0000ff24; | ||
} | ||
</style> | ||
<p>All this combined renders as follows:</p> | ||
<pre id="demo4" class="language-css line-numbers" style="white-space:pre-wrap;"><code><div id="demo4.1" class=line><a href="#demo4.1"></a> This is a demo code block to demonstrate the basic active line numbering functionality of the Lines plugin. | ||
</div><div id="demo4.2" class=line><a href="#demo4.2"></a> | ||
</div><div id="demo4.3" class=line><a href="#demo4.3"></a> It is not as sophisticated as the one provided by the Line Highlight plugin when it is used together with the Line Numbers plugin, but on the other hand this version is super lightweight and does not rely on any Javascript code at run-time. | ||
</div><div id="demo4.4" class=line><a href="#demo4.4"></a> | ||
</div><div id="demo4.5" class=line><a href="#demo4.5"></a> One thing worth mentioning is that the line numbers are right-clickable and you can "Save the link" instead of just clicking to get through.</div></code></pre> | ||
</section> | ||
|
||
<footer data-src="templates/footer.html" data-type="text/html"></footer> | ||
|
||
<script src="prism.js"></script> | ||
<script src="plugins/lines/prism-lines.js"></script> | ||
<script src="scripts/utopia.js"></script> | ||
<script src="components.js"></script> | ||
<script src="scripts/code.js"></script> | ||
|
||
|
||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
/* Protects from themes that mess the code block up */ | ||
pre[class*="language-"] > code { | ||
position: relative; | ||
display: block; | ||
} | ||
|
||
pre[class*="language-"] div.line { | ||
position: relative; | ||
display: block; | ||
height: 100%; | ||
line-height: inherit; | ||
text-indent: -1.5em; | ||
padding-left: 1.5em; | ||
} | ||
pre[class*="language-"] div.line::after { | ||
content: ''; | ||
position: absolute; | ||
display: block; | ||
top: 0; | ||
left: .5em; | ||
width: 100%; | ||
height: 100%; | ||
text-indent: 0; | ||
background: | ||
url(data:image/svg+xml;charset=utf-8;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDI0IDI0Ij48dGV4dCB4PSIwIiB5PSIxOSI+JiN4MjNjZTs8L3RleHQ+PC9zdmc+Cg==) | ||
no-repeat repeat; | ||
background-size: 1.5em 1.5em; | ||
clip: rect(1.5em 1.5em 100vh 0); | ||
opacity: .5; | ||
transform: rotateY(180deg); | ||
transform-origin: left; | ||
} | ||
|
||
/*** The following sample CSS code is disabled by default in order not to | ||
* angry lots of people since it kind of taps into other plugins' territory. | ||
* It is recommended to add the rules in the commented block below to your | ||
* local to your project CSS rule set and get the benefits described in the | ||
* plugin documentation. | ||
***/ | ||
|
||
/* Visually backward compatible replacement of the line-numbers plugin :) */ | ||
/* | ||
.line-numbers pre[class*="language-"], | ||
pre[class*="language-"].line-numbers { | ||
counter-reset: linenumber; | ||
counter-reset: linenumber var(--counter-start,0); | ||
padding-left: 0; | ||
} | ||
|
||
pre[class*="language-"] > code { | ||
white-space: inherit; | ||
} | ||
|
||
.line-numbers pre[class*="language-"] > code, | ||
pre[class*="language-"].line-numbers > code { | ||
padding-left: 3.8em; | ||
} | ||
|
||
.line-numbers pre[class*="language-"] div.line > a::before, | ||
pre[class*="language-"].line-numbers div.line > a::before { | ||
content: counter(linenumber); | ||
box-sizing: border-box; | ||
counter-increment: linenumber; | ||
color: #999; | ||
text-indent: 0; | ||
text-align: right; | ||
left: -3.8em; | ||
display: block; | ||
position: absolute; | ||
width: 3em; | ||
height: 100%; | ||
padding-right: .8em; | ||
border-right: solid #999; | ||
cursor: default; | ||
pointer-events: none; | ||
} | ||
|
||
.line-numbers pre[class*="language-"][id] div.line > a::before, | ||
pre[class*="language-"][id].line-numbers div.line > a::before { | ||
cursor: pointer; | ||
pointer-events: auto; | ||
} | ||
|
||
.line-numbers pre[class*="language-"][id] div.line > a:hover::before, | ||
pre[class*="language-"][id].line-numbers div.line > a:hover::before { | ||
color: black; | ||
background: rgba(0,0,0,.1); | ||
} | ||
*/ |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems more complicated than it has to be. How about: "Adds wrappers around lines to allow line-bases styling"?