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
Add line numbers library #46
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,5 @@ | ||
{{source}} | ||
<code class="hljs"> | ||
{{#if lineNumbers}} | ||
{{{source}}} | ||
{{else}}{{source}}{{/if}} | ||
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. To go with the previous comment about didInsertElement: let's remove this conditional and just always do the things that it does when lineNumbers=true. |
||
</code> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
(function(root) { | ||
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. Please add a comment like
ensuring of course that that's really the right URL and version number. |
||
"use strict"; | ||
|
||
function codeHighlightLinenums(code, opts) { | ||
opts = opts || {}; | ||
var hljs = opts.hljs, | ||
lang = opts.lang, | ||
start = opts.start || 0; | ||
// prevent errors by hljs | ||
code = code || ''; | ||
if(lang && /:/.test(lang)) { | ||
start = +lang.split(/:/)[1]; | ||
lang = lang.split(/:/)[0]; | ||
} else { | ||
start = +start; | ||
} | ||
|
||
if(hljs) { | ||
if(lang) { | ||
code = hljs.highlight(lang, code).value; | ||
} else { | ||
code = hljs.highlightAuto(code).value; | ||
} | ||
} | ||
|
||
if(start) { | ||
// move all closing spans to the previous line | ||
code = code.replace(/([\r\n]\s*)(<\/span>)/ig, '$2$1'); | ||
|
||
// replace spans with line-wraps inside them | ||
code = cleanLineBreaks(code); | ||
|
||
code = code.split(/\r\n|\r|\n/); | ||
var max = (start + code.length).toString().length; | ||
|
||
code = code | ||
.map(function(line, i) { | ||
return '<span class="line width-' + max + '" start="' + (start + i) + '">' + line + '</span>'; | ||
}) | ||
.join('\n'); | ||
} | ||
|
||
return code; | ||
} | ||
|
||
// Simplified parser that looks for opening & closing spans, and walks the tree. | ||
// If there are any unclosed spans when a newline is encountered, we close them on the previous line, | ||
// and copy them forward to the next line. | ||
function cleanLineBreaks(code) { | ||
var openSpans = [], | ||
matcher = /<\/?span[^>]*>|\r\n|\r|\n/ig, | ||
newline = /\r\n|\r|\n/, | ||
closingTag = /^<\//; | ||
|
||
return code.replace(matcher, function(match) { | ||
if(newline.test(match)) { | ||
if(openSpans.length) { | ||
return openSpans.map(function() { return '</span>' }).join('') + match + openSpans.join(''); | ||
} else { | ||
return match; | ||
} | ||
} else if(closingTag.test(match)) { | ||
openSpans.pop(); | ||
return match; | ||
} else { | ||
openSpans.push(match); | ||
return match; | ||
} | ||
}); | ||
} | ||
|
||
(function(factory) { | ||
if(typeof define === 'function' && define.amd) { | ||
// AMD. Register as an anonymous module. | ||
define(factory) | ||
} else if(typeof exports === 'object') { | ||
/** | ||
* Node. Does not work with strict CommonJS, but | ||
* only CommonJS-like environments that support module.exports, | ||
* like Node. | ||
*/ | ||
module.exports = factory(); | ||
} else { | ||
// Browser globals (root is window) | ||
root.codeHighlightLinenums = factory(); | ||
} | ||
}(function() { | ||
/** | ||
* Just return a value to define the module export. | ||
* This example returns an object, but the module | ||
* can return a function as the exported value. | ||
*/ | ||
return codeHighlightLinenums; | ||
})) | ||
|
||
})(this); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -118,4 +118,82 @@ | |
|
||
.hljs-chunk { | ||
color: #aaa; | ||
} | ||
} | ||
|
||
/* this uses the CSS suggested by | ||
https://github.com/OverZealous/code-highlight-linenums#example-lesscss | ||
*/ | ||
|
||
pre.code-snippet > code .line { | ||
display: inline-block; | ||
position: relative; | ||
padding-left: calc(2ch + 18px); | ||
} | ||
|
||
pre.code-snippet > code .line:before { | ||
box-sizing: content-box; | ||
display: inline-block; | ||
position: absolute; | ||
top: 0; | ||
bottom: 0; | ||
text-align: right; | ||
width: 2ch; | ||
content: attr(start); | ||
padding-right: 9px; | ||
padding-left: 9px; | ||
margin-left: calc(-2ch - 27px); | ||
margin-right: 9px; | ||
} | ||
|
||
pre.code-snippet > code .line:after { | ||
content: ' '; | ||
} | ||
|
||
|
||
pre.code-snippet > code .line:first-child:before { | ||
padding-top: 9px; | ||
margin-top: -9px; | ||
border-bottom-left-radius: 1em; | ||
} | ||
|
||
pre.code-snippet > code .line:last-child:before { | ||
padding-bottom: 9px; | ||
margin-bottom: -9px; | ||
border-bottom-left-radius: 1em; | ||
} | ||
|
||
pre.code-snippet > code .line.width-3 { | ||
padding-left: calc(3ch + 18px); | ||
} | ||
|
||
pre.code-snippet > code .line.width-3:before { | ||
width: 3ch; | ||
margin-left: calc(-3ch - 27px); | ||
} | ||
|
||
pre.code-snippet > code .line.width-4 { | ||
padding-left: calc(4ch + 18px); | ||
} | ||
|
||
pre.code-snippet > code .line.width-4:before { | ||
width: 4ch; | ||
margin-left: calc(-4ch - 27px); | ||
} | ||
|
||
pre.code-snippet > code .line.width-5 { | ||
padding-left: calc(5ch + 18px); | ||
} | ||
|
||
pre.code-snippet > code .line.width-5:before { | ||
width: 5ch; | ||
margin-left: calc(-5ch - 27px); | ||
} | ||
|
||
pre.code-snippet > code .line.width-6 { | ||
padding-left: calc(6ch + 18px); | ||
} | ||
|
||
pre.code-snippet > code .line.width-6:before { | ||
width: 6ch; | ||
margin-left: calc(-6ch - 27px); | ||
} | ||
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. This whole file won't be included if the user chooses to install their own theme. Maybe that's OK? But if they install stock highlight.js themes they will lack styling for the line numbers. An alternative would be to make this a separate CSS file that gets included whenever the code numbers JS file also gets included. If this CSS works well with many different highlight.js themes, that would probably be best. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
(function() { | ||
function vendorModule() { | ||
'use strict'; | ||
|
||
return { | ||
'default': self['codeHighlightLinenums'], | ||
__esModule: true, | ||
}; | ||
} | ||
|
||
define('code-highlight-linenums', [], vendorModule); | ||
})(); |
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.
For consistency, let's eliminate didInsertElement and always render
{{{source}}}
, regardless of whether lineNumbers is true or false.Otherwise the fastboot behavior is different based on whether you set lineNumbers, which would be surprising.