simple-confluence-to-markdown
Version:
Convert Confluence Pages to Markdown
363 lines (301 loc) • 11.2 kB
JavaScript
// Generated by CoffeeScript 1.12.7
(function() {
var Formatter;
Formatter = (function() {
/**
* @param {cheerio} _cheerio Required lib
* @param {Utils} utils My lib
* @param {Logger} logger My lib
*/
function Formatter(_cheerio, utils, logger) {
this._cheerio = _cheerio;
this.utils = utils;
this.logger = logger;
}
/**
* @param {string} text Content of a file
* @return {cheerio obj} Root object of a text
*/
Formatter.prototype.load = function(text) {
return this._cheerio.load(text);
};
/**
* @param {cheerio obj} $content Content of a file
* @return {string} Textual representation of a content
*/
Formatter.prototype.getText = function($content) {
return $content.text();
};
/**
* @param {cheerio obj} $content Content of a file
* @return {string} HTML representation of a content
*/
Formatter.prototype.getHtml = function($content) {
var $, contentHtml;
$ = this._cheerio;
contentHtml = '';
$content.each((function(_this) {
return function(i, el) {
return contentHtml += $(el).html();
};
})(this));
return contentHtml;
};
/**
* The right content is selected based on the filename given.
* Actual content of a page is placed elsewhere for index.html and other pages.
* @see load() You need to load the content first.
* @param {string} fileName Name of a file
*/
Formatter.prototype.getRightContentByFileName = function($content, fileName) {
var selector;
if (fileName === 'index.html') {
return $content.find('#content').find('#main-content>.confluenceTable').remove().end();
} else {
selector = ['#main-content', '.pageSection.group:has(.pageSectionHeader>#attachments)', '.pageSection.group:has(.pageSectionHeader>#comments)'];
return $content.find(selector.join(', '));
}
};
/**
* Removes span inside of a h1 tag.
* @param {cheerio obj} $content Content of a file
* @return {cheerio obj} Cheerio object
*/
Formatter.prototype.fixHeadline = function($content) {
return this._removeElementLeaveText($content, 'span.aui-icon');
};
Formatter.prototype.addPageHeading = function($content, headingText) {
var $, h1;
$ = this._cheerio;
h1 = $('<h1>').text(headingText);
$content.first().prepend(h1);
return $content;
};
/**
* Removes redundant icon
* @param {cheerio obj} $content Content of a file
* @return {cheerio obj} Cheerio object
*/
Formatter.prototype.fixIcon = function($content) {
return this._removeElementLeaveText($content, 'span.aui-icon');
};
/**
* Removes empty link
* @param {cheerio obj} $content Content of a file
* @return {cheerio obj} Cheerio object
*/
Formatter.prototype.fixEmptyLink = function($content) {
var $;
$ = this._cheerio;
return $content.find('a').each((function(_this) {
return function(i, el) {
if ($(el).text().trim().length === 0 && $(el).find('img').length === 0) {
return $(el).remove();
}
};
})(this)).end();
};
/**
* Removes empty heading
* @param {cheerio obj} $content Content of a file
* @return {cheerio obj} Cheerio object
*/
Formatter.prototype.fixEmptyHeading = function($content) {
var $;
$ = this._cheerio;
return $content.find(':header').each((function(_this) {
return function(i, el) {
if ($(el).text().trim().length === 0) {
return $(el).remove();
}
};
})(this)).end();
};
/**
* Gives the right class to syntaxhighlighter
* @param {cheerio obj} $content Content of a file
* @return {cheerio obj} Cheerio object
*/
Formatter.prototype.fixPreformattedText = function($content) {
var $;
$ = this._cheerio;
return $content.find('pre').each((function(_this) {
return function(i, el) {
var brush, data, styles;
data = $(el).data('syntaxhighlighterParams');
$(el).attr('style', data);
styles = $(el).css();
brush = styles != null ? styles.brush : void 0;
$(el).removeAttr('class');
if (brush) {
return $(el).addClass(brush);
}
};
})(this)).end();
};
/**
* Fixes 'p > a > span > img' for which no image was created.
* @param {cheerio obj} $content Content of a file
* @return {cheerio obj} Cheerio object
*/
Formatter.prototype.fixImageWithinSpan = function($content) {
var $;
$ = this._cheerio;
return $content.find('span:has(img)').each((function(_this) {
return function(i, el) {
if ($(el).text().trim().length === 0) {
return $(el).replaceWith($(el).html());
}
};
})(this)).end();
};
Formatter.prototype.removeArbitraryElements = function($content) {
return this._removeElementLeaveText($content, 'span, .user-mention, a[rel="nofollow"]');
};
/**
* Removes arbitrary confluence classes.
* @param {cheerio obj} $content Content of a file
* @return {cheerio obj} Cheerio object
*/
Formatter.prototype.fixArbitraryClasses = function($content) {
return $content.find('*').removeClass(function(i, e) {
return (e.match(/(^|\s)(confluence\-\S+|external-link|uri|tablesorter-header-inner|odd|even|header)/g) || []).join(' ');
}).end();
};
/**
* Removes arbitrary confluence elements for attachments.
* @param {cheerio obj} $content Content of a file
* @return {cheerio obj} Cheerio object
*/
Formatter.prototype.fixAttachmentWraper = function($content) {
return $content.find('.attachment-buttons').remove().end().find('.plugin_attachments_upload_container').remove().end().find('table.attachments.aui').remove().end();
};
/**
* Removes arbitrary confluence elements for attachments 2.
* @param {cheerio obj} $content Content of a file
* @return {cheerio obj} Cheerio object
*/
Formatter.prototype.fixAttachmentWrapper2 = function($content) {
return $content.find('.pageSectionHeader').remove().end().find('.greybox').remove().end()
};
/**
* 修复图片引用,去掉不必要的其他属性
* @param {cheerio obj} $content Content of a file
* @return {cheerio obj} Cheerio object
*/
Formatter.prototype.fixImageAndA = function($content) {
var $;
$ = this._cheerio;
return $content.find('img,a').each((function(_this) {
return function(i, el) {
$(el).removeAttr('draggable');
$(el).removeAttr('width');
$(el).removeAttr('height');
$(el).removeAttr('data-image-src');
$(el).removeAttr('data-linked-resource-id');
$(el).removeAttr('data-unresolved-comment-count');
$(el).removeAttr('data-linked-resource-version');
$(el).removeAttr('data-linked-resource-type');
$(el).removeAttr('data-linked-resource-default-alias');
$(el).removeAttr('data-base-url');
$(el).removeAttr('data-linked-resource-content-type');
$(el).removeAttr('data-linked-resource-container-id');
$(el).removeAttr('data-linked-resource-container-version');
};
})(this)).end();
};
/**
* 修订Image
* @param {cheerio obj} $content Content of a file
* @return {cheerio obj} Cheerio object
*/
Formatter.prototype.fixAWithinSpanImg = function($content) {
var $;
$ = this._cheerio;
var resourcesList = []
$content.find('.greybox').find('a').each(function (i, el) {
resourcesList.push({ text: $(el).text(), link: $(el).attr('href'), type: $(el).text() })
})
return $content.find('span[class="confluence-embedded-file-wrapper"]:has(a)').each((function(_this) {
return function(i, el) {
if ($(el).find('img').length !== 0) {
var mAEl = $(el).find('a')
const resourceId = mAEl.attr('data-linked-resource-id')
const rInfo = resourcesList.find(r => r.link.indexOf(resourceId) !== -1)
if (rInfo) {
var aEl = $('<a></a>').attr('href', rInfo.link).text(rInfo.text)
$(el).replaceWith(aEl);
}
}
};
})(this)).end();
};
/**
* Removes arbitrary confluence elements for page log.
* @param {cheerio obj} $content Content of a file
* @return {cheerio obj} Cheerio object
*/
Formatter.prototype.fixPageLog = function($content) {
return $content.find('[id$="Recentspaceactivity"], [id$=Spacecontributors]').parent().remove().end().end();
};
/**
* Changes links to local HTML files to generated MD files.
* @param {cheerio obj} $content Content of a file
* @param {string} cwd Current working directory (where HTML file reside)
* @return {cheerio obj} Cheerio object
*/
Formatter.prototype.fixLocalLinks = function($content, space, pages) {
var $;
$ = this._cheerio;
return $content.find('a').each((function(_this) {
return function(i, el) {
var href, pageLink, text;
href = $(el).attr('href');
if (href === void 0) {
text = $(el).text();
$(el).replaceWith(text);
return _this.logger.debug('No href for link with text "#{text}"');
} else if ($(el).hasClass('createlink')) {
return $(el).replaceWith($(el).text());
} else if (pageLink = _this.utils.getLinkToNewPageFile(href, pages, space)) {
return $(el).attr('href', pageLink);
}
};
})(this)).end();
};
/**
* @param {array} indexHtmlFiles Relative paths of index.html files from all parsed Confluence spaces
* @return {cheerio obj} Cheerio object
*/
Formatter.prototype.createListFromArray = function(itemArray) {
var $, $a, $li, $ul, item, j, len;
$ = this._cheerio.load('<ul>');
$ul = $('ul');
for (j = 0, len = itemArray.length; j < len; j++) {
item = itemArray[j];
$a = $('<a>').attr('href', item).text(item.replace('/index', ''));
$li = $('<li>');
$li.append($a);
$ul.append($li);
}
return $ul.end();
};
/**
* Removes element by selector and leaves only its text content
* @param {cheerio obj} $content Content of a file
* @param {string} selector Selector of an element
* @return {cheerio obj} Cheerio object
*/
Formatter.prototype._removeElementLeaveText = function($content, selector) {
var $;
$ = this._cheerio;
return $content.find(selector).each((function(_this) {
return function(i, el) {
return $(el).replaceWith($(el).text());
};
})(this)).end();
};
return Formatter;
})();
module.exports = Formatter;
}).call(this);