Skip to content
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 support for JSDoc and fix tab size and alignment #6

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions src/github.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,16 @@ function process() {
if (openPuncs.test(puncs[i].textContent)) puncs[i].classList.add('open')
}

var blobs = document.querySelectorAll('.blob-wrapper')
var blobs = document.querySelectorAll('.blob-wrapper > table')
for (var i = 0; i < blobs.length; i++) {
etab.processLines(blobs[i].querySelectorAll('.blob-code'))
var localEtab = etab
var blob = blobs[i]
if (blob.dataset.tabSize && blob.dataset.tabSize !== 8) {
localEtab = new ElasticTabstops({
tabIndentExtraSpace: blob.dataset.tabSize
})
}
localEtab.processLines(blobs[i].querySelectorAll('.blob-code'))
}
}

Expand Down
70 changes: 50 additions & 20 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,53 +4,80 @@ var TAB = '\t'
var SPACE = ' '
var TEXT_NODE = 3

/**
* Creates a new ElasticTabstops instance.
*
* @public
*
* @param {Object} [settings={}] The settings object.
* @param {String} [settings.tabTagName='span'] The tab tag name.
* @param {String} [settings.tabClassName='tab-char'] The tab tag class.
* @param {String} [settings.indentClassName='indent'] The indentation class.
* @param {String} [settings.tabIndentExtraSpace=8] The width of indentation tabs, in spaces.
* @param {String} [settings.tabSpaceMinWidth='1ch'] The minimum width of a tab, defaults to the size of a space.
* @param {String} [settings.styleId='etab-style'] The ID of the &lt;style&gt; tag.
* @param {String[]} [settings.styleRules=] The content of the &lt;style&gt; tag.
*
* @returns {ElasticTabstops} The ElasticTabstops instance
*/
function ElasticTabstops(settings) {
var s = settings || {}
this.settings = {
tabTagName : s.tabTagName || 'span',
tabClassName : s.tabClassName || 'tab-char',
//tabIndentWidth : s.tabIndentWidth || '1.5em',
indentClassName : s.indentClassName || 'ident',
tabIndentExtraSpace : 8,
tabSpaceMinWidth : s.tabSpaceMinWidth || '1em',
styleId : s.styleId || 'etab-style',
styleRules : s.styleRules || [],
tabIndentExtraSpace : s.tabIndentExtraSpace || 8,
tabSpaceMinWidth : s.tabSpaceMinWidth || '1ch',
styleId : s.styleId || 'etab-style',
styleRules : s.styleRules || [],
//openPunctuations : s.openPunctuations || '"\'([{“‘', // Unicode categories Ps, Pf, Pi
//hangingPunctutaion : s.hangingPunctutaion !== undefined ? !!s.hangingPunctutaion : true,
//openClassName : s.openClassName || 'open',
}
}

/**
* @private
* @param {type} doc
* @returns {undefined}
*/
ElasticTabstops.prototype._addStyle = function (doc) {
if (doc.getElementById(this.settings.styleId)) return
var s = doc.createElement('style')
s.id = this.settings.styleId
doc.body.appendChild(s)
var sel = this.settings.tabTagName + '.' + this.settings.tabClassName
s.sheet.insertRule(sel + '{ display: inline-block; margin-right: ' + this.settings.tabSpaceMinWidth + ' }', 0)
s.sheet.insertRule(sel + '{ display: inline-block; min-width: ' + this.settings.tabSpaceMinWidth + ' }', 0)
s.sheet.insertRule(sel + ".ident" + '{ min-width: ' + this.settings.tabIndentExtraSpace + 'ch }', 0)
this.settings.styleRules.forEach(function (rule, i) {
s.sheet.insertRule(rule, i + 1)
})
}

ElasticTabstops.prototype.testLines = function (lineNodes) {
var etabPattern = /[^\t]+\t/
var state = false
for (var i = 0, n = lineNodes.length; i < n; i++) {
var text = lineNodes[i].textContent
if (text.charAt(0) === SPACE) return false
// if (text.charAt(0) === SPACE) return false // BREAKS ON LICENSE HEADERS AND ON JSDOC!
if (etabPattern.test(text)) {
if (state) return true
else state = true
} else {
state = false
return true
}
}
return false
return false // The document doesn't have any non-indentation tabs.
}

/**
* Processes the document.
*
* @public
*
* @param {NodeList} lineNodes The nodes containing the text
*
* @returns {undefined}
*/
ElasticTabstops.prototype.processLines = function (lineNodes) {

if (!this.testLines(lineNodes)) return

this._addStyle(lineNodes[0].ownerDocument)
Expand All @@ -64,7 +91,7 @@ ElasticTabstops.prototype.processLines = function (lineNodes) {
var index = lines.map(function (l) { return new Array(l.length) })

var settings = this.settings

alignNext(0, 0)

function alignNext(row, col) {
Expand All @@ -78,17 +105,20 @@ ElasticTabstops.prototype.processLines = function (lineNodes) {
setTimeout(function () { alignNext(row, col + 1) })
}

/**
* @private
* @param {HTMLElement[]} cells
* @returns {undefined}
*/
function doAlign(cells) {
var rights = cells.map(function (x) {
var r = x.getBoundingClientRect().right
if (x.classList.contains(settings.indentClassName)) r += settings.tabIndentExtraSpace
return r
return x.getBoundingClientRect().right
})
var rightmost = Math.max.apply(null, rights)
cells.forEach(function (x) {
x.style.width = (rightmost - x.getBoundingClientRect().right) + 'px'
x.style.width = 'calc(' + (rightmost - x.getBoundingClientRect().right) + 'px + ' + settings.tabSpaceMinWidth + ')'
})
cells.aligned = true
cells.aligned = true
}

function alignCells(row, col) {
Expand Down Expand Up @@ -140,7 +170,7 @@ ElasticTabstops.prototype._wrapTab = function wrapTab(tab, indent) {
}

ElasticTabstops.prototype._isTab = function isTab(e) {
return e.nodeName === this.settings.tabTagName &&
return e.nodeName.toUpperCase() === this.settings.tabTagName.toUpperCase() &&
e.classList.contains(this.settings.tabClassName)
}

Expand Down