mirror of
https://github.com/alexadam/save-as-ebook.git
synced 2025-09-11 01:44:44 +00:00
styles - wip
This commit is contained in:
parent
9f3d349ffe
commit
7dd34efee5
10 changed files with 1119 additions and 38 deletions
|
@ -1,3 +1,5 @@
|
||||||
|
// var GLOBAL_CURRENT_STYLE = null;
|
||||||
|
|
||||||
|
|
||||||
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
|
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
|
||||||
if (request.type === 'get') {
|
if (request.type === 'get') {
|
||||||
|
@ -27,5 +29,29 @@ chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
|
||||||
if (request.type === 'set title') {
|
if (request.type === 'set title') {
|
||||||
chrome.storage.local.set({'title': request.title});
|
chrome.storage.local.set({'title': request.title});
|
||||||
}
|
}
|
||||||
|
if (request.type === 'get styles') {
|
||||||
|
chrome.storage.local.get('styles', function (data) {
|
||||||
|
if (!data || !data.styles) {
|
||||||
|
sendResponse({styles: []});
|
||||||
|
} else {
|
||||||
|
sendResponse({styles: data.styles});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (request.type === 'set styles') {
|
||||||
|
chrome.storage.local.set({'styles': request.styles});
|
||||||
|
}
|
||||||
|
if (request.type === 'get current style') {
|
||||||
|
chrome.storage.local.get('currentStyle', function (data) {
|
||||||
|
if (!data || !data.currentStyle) {
|
||||||
|
sendResponse({currentStyle: 0});
|
||||||
|
} else {
|
||||||
|
sendResponse({currentStyle: data.currentStyle});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (request.type === 'set current style') {
|
||||||
|
chrome.storage.local.set({'currentStyle': request.currentStyle});
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
181
web-extension/cssEditor.css
Normal file
181
web-extension/cssEditor.css
Normal file
|
@ -0,0 +1,181 @@
|
||||||
|
body.dragging, body.dragging * {
|
||||||
|
cursor: move !important;
|
||||||
|
}
|
||||||
|
.dragged {
|
||||||
|
position: absolute;
|
||||||
|
opacity: 0.5;
|
||||||
|
z-index: 2000;
|
||||||
|
}
|
||||||
|
ul.cssEditor-chapters-list li.placeholder {
|
||||||
|
position: relative;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
border: solid 10px #f5f5f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cssEditor-Title {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
float: left;
|
||||||
|
display: inline-block;
|
||||||
|
font-family: "sans-serif";
|
||||||
|
}
|
||||||
|
|
||||||
|
#cssEditor-ebookTitleHolder {
|
||||||
|
background-color: #eee;
|
||||||
|
padding: 10px 20px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
#cssEditor-ebookTitleLabel {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 18px;
|
||||||
|
font-family: sans-serif;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
#cssEditor-ebookTitle {
|
||||||
|
padding: 5px;
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: "sans-serif";
|
||||||
|
width: 85%;
|
||||||
|
}
|
||||||
|
ul, ul.cssEditor-chapters-list {
|
||||||
|
width: 100%;
|
||||||
|
display: block;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
list-style-type: none !important;
|
||||||
|
}
|
||||||
|
.cssEditor-chapter-item {
|
||||||
|
display: block;
|
||||||
|
line-height: 35px;
|
||||||
|
height: 35px;
|
||||||
|
padding: 5px 0;
|
||||||
|
vertical-align: middle;
|
||||||
|
font-size: 17px;
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
.cssEditor-chapter-item:hover {
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
}
|
||||||
|
.cssEditor-drag-handler {
|
||||||
|
cursor: move;
|
||||||
|
padding: 3px;
|
||||||
|
margin-right: 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
.cssEditor-chapter-item > input[type="text"] {
|
||||||
|
padding: 5px;
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: "sans-serif";
|
||||||
|
width: 80%;
|
||||||
|
border: none;
|
||||||
|
border-bottom: solid 1px #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cssEditor-modalHeader {
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
#cssEditor-modalList {
|
||||||
|
display: block;
|
||||||
|
/*width: 100%;*/
|
||||||
|
/*border-top: solid 1px black;*/
|
||||||
|
/*border-bottom: solid 1px black;*/
|
||||||
|
padding: 20px;
|
||||||
|
padding-top: 0;
|
||||||
|
}
|
||||||
|
#cssEditor-modalFooter {
|
||||||
|
display: block;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.chapter-item * {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
#dragHandler {
|
||||||
|
padding: 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.cssEditor-text-button {
|
||||||
|
border: none;
|
||||||
|
font-size: 15px;
|
||||||
|
font-family: "sans-serif";
|
||||||
|
padding: 5px;
|
||||||
|
background-color: rgba(0, 0, 0, 0);
|
||||||
|
margin: 0 3px;
|
||||||
|
outline: none;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.cssEditor-text-button:hover {
|
||||||
|
background-color: #000;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.cssEditor-text-red {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cssEditor-float-left {
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
.cssEditor-float-right {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cssEditor-footer-button {
|
||||||
|
padding: 18px 20px;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 18px;
|
||||||
|
border: none;
|
||||||
|
background-color: rgba(0, 0, 0, 0);
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.cssEditor-footer-button:hover {
|
||||||
|
color: white;
|
||||||
|
background-color: rgba(0, 0, 0, 1);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.cssEditor-save-button {
|
||||||
|
background-color: yellow;
|
||||||
|
}
|
||||||
|
.cssEditor-cancel-button {
|
||||||
|
/*background-color: black;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1700px) {
|
||||||
|
.cssEditor-chapter-item {
|
||||||
|
line-height: 30px;
|
||||||
|
height: 30px;
|
||||||
|
padding: 4px 0;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.cssEditor-chapter-item > input[type="text"] {
|
||||||
|
padding: 3px;
|
||||||
|
font-size: 12px;
|
||||||
|
width: 75%;
|
||||||
|
}
|
||||||
|
.cssEditor-text-button {
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 3px;
|
||||||
|
margin: 0 2px;
|
||||||
|
}
|
||||||
|
.cssEditor-footer-button {
|
||||||
|
padding: 15px 20px;
|
||||||
|
margin: 0;
|
||||||
|
font-size: 15px;
|
||||||
|
border: none;
|
||||||
|
background-color: rgba(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1100px) {
|
||||||
|
.cssEditor-chapter-item {
|
||||||
|
line-height: 30px;
|
||||||
|
height: 60px;
|
||||||
|
padding: 4px 0;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.cssEditor-chapter-item > input[type="text"] {
|
||||||
|
width: 90%;
|
||||||
|
}
|
||||||
|
}
|
356
web-extension/cssEditor.js
Normal file
356
web-extension/cssEditor.js
Normal file
|
@ -0,0 +1,356 @@
|
||||||
|
for (var i=0; i<document.styleSheets.length; i++) {
|
||||||
|
document.styleSheets.item(i).disabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var tmp = document.getElementById('cssEditor-Modal');
|
||||||
|
if (tmp) {
|
||||||
|
tmp.parentNode.removeChild(tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
var allPagesRef = null;
|
||||||
|
var allStyles = [{
|
||||||
|
title: 'reddit',
|
||||||
|
url: 'reddit.com',
|
||||||
|
style: `
|
||||||
|
.class: {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
}];
|
||||||
|
var currentStyle = null;
|
||||||
|
var currentStyleIndex = -1;
|
||||||
|
|
||||||
|
|
||||||
|
showEditor();
|
||||||
|
|
||||||
|
|
||||||
|
function showEditor() {
|
||||||
|
|
||||||
|
var body = document.getElementsByTagName('body')[0];
|
||||||
|
var modalContent = document.createElement('div');
|
||||||
|
modalContent.id = 'cssEditor-modalContent';
|
||||||
|
var modalHeader = document.createElement('div');
|
||||||
|
modalHeader.id = 'cssEditor-modalHeader';
|
||||||
|
var modalList = document.createElement('div');
|
||||||
|
modalList.id = 'cssEditor-modalList';
|
||||||
|
var modalFooter = document.createElement('div');
|
||||||
|
modalFooter.id = 'cssEditor-modalFooter';
|
||||||
|
|
||||||
|
////////
|
||||||
|
// Header
|
||||||
|
var title = document.createElement('span');
|
||||||
|
title.id = "cssEditor-Title";
|
||||||
|
title.innerText = "Style Editor";
|
||||||
|
var upperCloseButton = document.createElement('button');
|
||||||
|
modalHeader.appendChild(title);
|
||||||
|
upperCloseButton.onclick = closeModal;
|
||||||
|
upperCloseButton.innerText = 'X';
|
||||||
|
upperCloseButton.className = 'cssEditor-text-button cssEditor-float-right';
|
||||||
|
modalHeader.appendChild(upperCloseButton);
|
||||||
|
/////////////////////
|
||||||
|
// Content List
|
||||||
|
|
||||||
|
var titleHolder = document.createElement('div');
|
||||||
|
titleHolder.id = 'cssEditor-ebookTitleHolder';
|
||||||
|
|
||||||
|
var existingStyles = document.createElement('select');
|
||||||
|
existingStyles.id = "selectStyle";
|
||||||
|
existingStyles.onchange = function (event) {
|
||||||
|
if (existingStyles.selectedIndex === 0) {
|
||||||
|
currentStyle = null;
|
||||||
|
currentStyleIndex = -1;
|
||||||
|
hideStyleEditor();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
currentStyle = allStyles[existingStyles.selectedIndex - 1];
|
||||||
|
currentStyleIndex = existingStyles.selectedIndex - 1;
|
||||||
|
editCurrentStyle();
|
||||||
|
};
|
||||||
|
var defaultOption = document.createElement('option');
|
||||||
|
defaultOption.innerText = 'Select Existing CSS';
|
||||||
|
existingStyles.appendChild(defaultOption);
|
||||||
|
titleHolder.appendChild(existingStyles);
|
||||||
|
|
||||||
|
var titleLabel = document.createElement('label');
|
||||||
|
titleLabel.innerText = ' or ';
|
||||||
|
titleHolder.appendChild(titleLabel);
|
||||||
|
|
||||||
|
var createNewStyleButton = document.createElement('button');
|
||||||
|
createNewStyleButton.innerText = 'Create New Style';
|
||||||
|
createNewStyleButton.className = 'cssEditor-cancel-button';
|
||||||
|
createNewStyleButton.onclick = createNewStyle;
|
||||||
|
titleHolder.appendChild(createNewStyleButton);
|
||||||
|
|
||||||
|
modalList.appendChild(titleHolder);
|
||||||
|
|
||||||
|
function createNewStyle() {
|
||||||
|
currentStyle = null;
|
||||||
|
currentStyleIndex = -1;
|
||||||
|
resetFields();
|
||||||
|
showStyleEditor();
|
||||||
|
hideRemoveStyle();
|
||||||
|
createStyleList();
|
||||||
|
}
|
||||||
|
|
||||||
|
//////
|
||||||
|
|
||||||
|
var editorHolder = document.createElement('div');
|
||||||
|
editorHolder.style.display = 'none';
|
||||||
|
editorHolder.id = 'cssEditor-styleEditor';
|
||||||
|
|
||||||
|
var nameLabelHolder = document.createElement('div');
|
||||||
|
var nameLabel = document.createElement('label');
|
||||||
|
nameLabel.innerText = 'Name';
|
||||||
|
nameLabelHolder.appendChild(nameLabel);
|
||||||
|
editorHolder.appendChild(nameLabelHolder);
|
||||||
|
|
||||||
|
var nameInputHolder = document.createElement('div');
|
||||||
|
var cssNameInput = document.createElement('input');
|
||||||
|
cssNameInput.id = 'cssEditor-styleName';
|
||||||
|
cssNameInput.type = 'text';
|
||||||
|
nameInputHolder.appendChild(cssNameInput);
|
||||||
|
editorHolder.appendChild(nameInputHolder);
|
||||||
|
|
||||||
|
|
||||||
|
var urlLabelHolder = document.createElement('div');
|
||||||
|
var urlLabel = document.createElement('label');
|
||||||
|
urlLabel.innerText = 'URL Starts With';
|
||||||
|
urlLabelHolder.appendChild(urlLabel);
|
||||||
|
editorHolder.appendChild(urlLabelHolder);
|
||||||
|
|
||||||
|
var urlInputHolder = document.createElement('div');
|
||||||
|
var urlInput = document.createElement('input');
|
||||||
|
urlInput.id = 'cssEditor-matchUrl';
|
||||||
|
urlInput.type = 'text';
|
||||||
|
urlInputHolder.appendChild(urlInput);
|
||||||
|
editorHolder.appendChild(urlInputHolder);
|
||||||
|
|
||||||
|
var contentLabelHolder = document.createElement('div');
|
||||||
|
var contentLabel = document.createElement('label');
|
||||||
|
contentLabel.innerText = 'CSS';
|
||||||
|
contentLabelHolder.appendChild(contentLabel);
|
||||||
|
editorHolder.appendChild(contentLabelHolder);
|
||||||
|
|
||||||
|
var contentInputHolder = document.createElement('div');
|
||||||
|
var contentInput = document.createElement('textarea');
|
||||||
|
contentInput.id = 'cssEditor-styleContent';
|
||||||
|
contentInputHolder.appendChild(contentInput);
|
||||||
|
editorHolder.appendChild(contentInputHolder);
|
||||||
|
|
||||||
|
modalList.appendChild(editorHolder);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var saveButtonsHolder = document.createElement('div');
|
||||||
|
|
||||||
|
var removeCssButton = document.createElement('button');
|
||||||
|
removeCssButton.id = 'cssEditor-removeStyle';
|
||||||
|
removeCssButton.innerText = 'Remove Style';
|
||||||
|
removeCssButton.className = 'cssEditor-footer-button cssEditor-float-left cssEditor-cancel-button';
|
||||||
|
removeCssButton.onclick = removeStyle;
|
||||||
|
saveButtonsHolder.appendChild(removeCssButton);
|
||||||
|
|
||||||
|
var saveCssButton = document.createElement('button');
|
||||||
|
saveCssButton.innerText = 'Save Style';
|
||||||
|
saveCssButton.className = 'cssEditor-footer-button cssEditor-float-right cssEditor-save-button';
|
||||||
|
saveCssButton.onclick = saveStyle;
|
||||||
|
saveButtonsHolder.appendChild(saveCssButton);
|
||||||
|
|
||||||
|
modalFooter.appendChild(saveButtonsHolder);
|
||||||
|
|
||||||
|
//////////////////////////
|
||||||
|
|
||||||
|
function createStyleList(allStylesTmp) {
|
||||||
|
if (allStylesTmp && allStylesTmp.length > 0) {
|
||||||
|
allStyles = allStyles.slice(0, 0).concat(allStylesTmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (existingStyles.hasChildNodes() && existingStyles.childElementCount > 1) {
|
||||||
|
existingStyles.removeChild(existingStyles.lastChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < allStyles.length; i++) {
|
||||||
|
var listItem = document.createElement('option');
|
||||||
|
listItem.id = 'option_' + i;
|
||||||
|
listItem.className = 'cssEditor-chapter-item';
|
||||||
|
listItem.value = 'option_' + i;
|
||||||
|
listItem.innerText = allStyles[i].title;
|
||||||
|
if (currentStyle && (allStyles[i].title === currentStyle.title)) {
|
||||||
|
listItem.selected = 'selected';
|
||||||
|
}
|
||||||
|
existingStyles.appendChild(listItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function editCurrentStyle() {
|
||||||
|
if (!currentStyle) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
showStyleEditor();
|
||||||
|
showRemoveStyle();
|
||||||
|
|
||||||
|
document.getElementById('cssEditor-styleName').value = currentStyle.title;
|
||||||
|
document.getElementById('cssEditor-matchUrl').value = currentStyle.url;
|
||||||
|
document.getElementById('cssEditor-styleContent').value = currentStyle.style;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetFields() {
|
||||||
|
document.getElementById('cssEditor-styleName').value = '';
|
||||||
|
document.getElementById('cssEditor-matchUrl').value = '';
|
||||||
|
document.getElementById('cssEditor-styleContent').value = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideStyleEditor() {
|
||||||
|
document.getElementById('cssEditor-styleEditor').style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
function showStyleEditor() {
|
||||||
|
document.getElementById('cssEditor-styleEditor').style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
|
function showRemoveStyle() {
|
||||||
|
document.getElementById('cssEditor-removeStyle').style.display = 'inline-block';
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideRemoveStyle() {
|
||||||
|
document.getElementById('cssEditor-removeStyle').style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveStyle() {
|
||||||
|
var tmpValue = {
|
||||||
|
title: document.getElementById('cssEditor-styleName').value,
|
||||||
|
url: document.getElementById('cssEditor-matchUrl').value,
|
||||||
|
style: document.getElementById('cssEditor-styleContent').value
|
||||||
|
}
|
||||||
|
if (currentStyle === null) {
|
||||||
|
allStyles.push(tmpValue);
|
||||||
|
currentStyle = tmpValue;
|
||||||
|
currentStyleIndex = allStyles.length - 1;
|
||||||
|
} else {
|
||||||
|
currentStyle = tmpValue;
|
||||||
|
allStyles[currentStyleIndex] = currentStyle;
|
||||||
|
}
|
||||||
|
setStyles(allStyles);
|
||||||
|
createStyleList();
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeStyle() {
|
||||||
|
allStyles.splice(currentStyleIndex, 1);
|
||||||
|
setStyles(allStyles);
|
||||||
|
hideStyleEditor();
|
||||||
|
createStyleList();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////
|
||||||
|
|
||||||
|
var modal = document.createElement('div');
|
||||||
|
modal.id = 'cssEditor-Modal';
|
||||||
|
|
||||||
|
modalContent.appendChild(modalHeader);
|
||||||
|
modalContent.appendChild(modalList);
|
||||||
|
modalContent.appendChild(modalFooter);
|
||||||
|
modal.appendChild(modalContent);
|
||||||
|
|
||||||
|
body.appendChild(modal);
|
||||||
|
|
||||||
|
modal.style.display = "none";
|
||||||
|
modal.style.position = 'fixed';
|
||||||
|
modal.style.zIndex = '1';
|
||||||
|
modal.style.left = '0';
|
||||||
|
modal.style.top = '0';
|
||||||
|
modal.style.width = '100%';
|
||||||
|
modal.style.height = '100%';
|
||||||
|
modal.style.overflow = 'auto';
|
||||||
|
modal.style.backgroundColor = 'rgba(210, 210, 210, 1)';
|
||||||
|
|
||||||
|
modalContent.style.zIndex = '2';
|
||||||
|
modalContent.style.backgroundColor = '#fff';
|
||||||
|
modalContent.style.margin = '5% auto';
|
||||||
|
modalContent.style.padding = '0';
|
||||||
|
modalContent.style.width = '70%';
|
||||||
|
|
||||||
|
window.onclick = function(event) {
|
||||||
|
if (event.target == modal) {
|
||||||
|
closeModal();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
modal.style.display = "block";
|
||||||
|
|
||||||
|
document.onkeydown = function(evt) {
|
||||||
|
evt = evt || window.event;
|
||||||
|
if (evt.keyCode == 27) {
|
||||||
|
closeModal();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function closeModal() {
|
||||||
|
for (var i=0; i<document.styleSheets.length; i++) {
|
||||||
|
document.styleSheets.item(i).disabled = false;
|
||||||
|
}
|
||||||
|
modal.style.display = "none";
|
||||||
|
modalContent.parentNode.removeChild(modalContent);
|
||||||
|
modal.parentNode.removeChild(modal);
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeListItem(atIndex) {
|
||||||
|
return function() {
|
||||||
|
allPagesRef[atIndex].removed = true;
|
||||||
|
var tmpListElem = document.getElementById('li' + atIndex);
|
||||||
|
tmpListElem.style.display = 'none';
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function previewListItem(atIndex) {
|
||||||
|
return function() {
|
||||||
|
alert(allPagesRef[atIndex].content.trim().replace(/<[^>]+>/gi, '').replace(/\s+/g, ' ').substring(0, 1000) + ' ...');
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function prepareEbook(newChapters) {
|
||||||
|
try {
|
||||||
|
if (newChapters.length === 0) {
|
||||||
|
alert('Can\'t generate an empty eBook!');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
buildEbookFromChapters();
|
||||||
|
} catch (e) {
|
||||||
|
console.log('Error:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveChanges() {
|
||||||
|
var newChapters = [];
|
||||||
|
var newEbookTitle = ebookTilte.value;
|
||||||
|
if (newEbookTitle.trim() === '') {
|
||||||
|
newEbookTitle = 'eBook';
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
var tmpChaptersList = document.getElementsByClassName('cssEditor-chapter-item');
|
||||||
|
if (!tmpChaptersList || !allPagesRef) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < tmpChaptersList.length; i++) {
|
||||||
|
var listIndex = Number(tmpChaptersList[i].id.replace('li', ''));
|
||||||
|
if (allPagesRef[listIndex].removed === false) {
|
||||||
|
newChapters.push(allPagesRef[listIndex]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
saveEbookTitle(newEbookTitle);
|
||||||
|
saveEbookPages(newChapters);
|
||||||
|
return newChapters;
|
||||||
|
} catch (e) {
|
||||||
|
console.log('Error:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////
|
||||||
|
|
||||||
|
getStyles(createStyleList);
|
||||||
|
}
|
297
web-extension/cssjson.js
Normal file
297
web-extension/cssjson.js
Normal file
|
@ -0,0 +1,297 @@
|
||||||
|
/**
|
||||||
|
* CSS-JSON Converter for JavaScript
|
||||||
|
* Converts CSS to JSON and back.
|
||||||
|
* Version 2.1
|
||||||
|
*
|
||||||
|
* Released under the MIT license.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013 Aram Kocharyan, http://aramk.com/
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||||
|
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
|
||||||
|
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
|
||||||
|
to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions
|
||||||
|
of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||||
|
THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var CSSJSON = new function () {
|
||||||
|
|
||||||
|
var base = this;
|
||||||
|
|
||||||
|
base.init = function () {
|
||||||
|
// String functions
|
||||||
|
String.prototype.trim = function () {
|
||||||
|
return this.replace(/^\s+|\s+$/g, '');
|
||||||
|
};
|
||||||
|
|
||||||
|
String.prototype.repeat = function (n) {
|
||||||
|
return new Array(1 + n).join(this);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
base.init();
|
||||||
|
|
||||||
|
var selX = /([^\s\;\{\}][^\;\{\}]*)\{/g;
|
||||||
|
var endX = /\}/g;
|
||||||
|
var lineX = /([^\;\{\}]*)\;/g;
|
||||||
|
var commentX = /\/\*[\s\S]*?\*\//g;
|
||||||
|
var lineAttrX = /([^\:]+):([^\;]*);/;
|
||||||
|
|
||||||
|
// This is used, a concatenation of all above. We use alternation to
|
||||||
|
// capture.
|
||||||
|
var altX = /(\/\*[\s\S]*?\*\/)|([^\s\;\{\}][^\;\{\}]*(?=\{))|(\})|([^\;\{\}]+\;(?!\s*\*\/))/gmi;
|
||||||
|
|
||||||
|
// Capture groups
|
||||||
|
var capComment = 1;
|
||||||
|
var capSelector = 2;
|
||||||
|
var capEnd = 3;
|
||||||
|
var capAttr = 4;
|
||||||
|
|
||||||
|
var isEmpty = function (x) {
|
||||||
|
return typeof x == 'undefined' || x.length == 0 || x == null;
|
||||||
|
};
|
||||||
|
|
||||||
|
var isCssJson = function (node) {
|
||||||
|
return !isEmpty(node) ? (node.attributes && node.children) : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Input is css string and current pos, returns JSON object
|
||||||
|
*
|
||||||
|
* @param cssString
|
||||||
|
* The CSS string.
|
||||||
|
* @param args
|
||||||
|
* An optional argument object. ordered: Whether order of
|
||||||
|
* comments and other nodes should be kept in the output. This
|
||||||
|
* will return an object where all the keys are numbers and the
|
||||||
|
* values are objects containing "name" and "value" keys for each
|
||||||
|
* node. comments: Whether to capture comments. split: Whether to
|
||||||
|
* split each comma separated list of selectors.
|
||||||
|
*/
|
||||||
|
base.toJSON = function (cssString, args) {
|
||||||
|
var node = {
|
||||||
|
children: {},
|
||||||
|
attributes: {}
|
||||||
|
};
|
||||||
|
var match = null;
|
||||||
|
var count = 0;
|
||||||
|
|
||||||
|
if (typeof args == 'undefined') {
|
||||||
|
var args = {
|
||||||
|
ordered: false,
|
||||||
|
comments: false,
|
||||||
|
stripComments: false,
|
||||||
|
split: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (args.stripComments) {
|
||||||
|
args.comments = false;
|
||||||
|
cssString = cssString.replace(commentX, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((match = altX.exec(cssString)) != null) {
|
||||||
|
if (!isEmpty(match[capComment]) && args.comments) {
|
||||||
|
// Comment
|
||||||
|
var add = match[capComment].trim();
|
||||||
|
node[count++] = add;
|
||||||
|
} else if (!isEmpty(match[capSelector])) {
|
||||||
|
// New node, we recurse
|
||||||
|
var name = match[capSelector].trim();
|
||||||
|
// This will return when we encounter a closing brace
|
||||||
|
var newNode = base.toJSON(cssString, args);
|
||||||
|
if (args.ordered) {
|
||||||
|
var obj = {};
|
||||||
|
obj['name'] = name;
|
||||||
|
obj['value'] = newNode;
|
||||||
|
// Since we must use key as index to keep order and not
|
||||||
|
// name, this will differentiate between a Rule Node and an
|
||||||
|
// Attribute, since both contain a name and value pair.
|
||||||
|
obj['type'] = 'rule';
|
||||||
|
node[count++] = obj;
|
||||||
|
} else {
|
||||||
|
if (args.split) {
|
||||||
|
var bits = name.split(',');
|
||||||
|
} else {
|
||||||
|
var bits = [name];
|
||||||
|
}
|
||||||
|
for (i in bits) {
|
||||||
|
var sel = bits[i].trim();
|
||||||
|
if (sel in node.children) {
|
||||||
|
for (var att in newNode.attributes) {
|
||||||
|
node.children[sel].attributes[att] = newNode.attributes[att];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
node.children[sel] = newNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (!isEmpty(match[capEnd])) {
|
||||||
|
// Node has finished
|
||||||
|
return node;
|
||||||
|
} else if (!isEmpty(match[capAttr])) {
|
||||||
|
var line = match[capAttr].trim();
|
||||||
|
var attr = lineAttrX.exec(line);
|
||||||
|
if (attr) {
|
||||||
|
// Attribute
|
||||||
|
var name = attr[1].trim();
|
||||||
|
var value = attr[2].trim();
|
||||||
|
if (args.ordered) {
|
||||||
|
var obj = {};
|
||||||
|
obj['name'] = name;
|
||||||
|
obj['value'] = value;
|
||||||
|
obj['type'] = 'attr';
|
||||||
|
node[count++] = obj;
|
||||||
|
} else {
|
||||||
|
if (name in node.attributes) {
|
||||||
|
var currVal = node.attributes[name];
|
||||||
|
if (!(currVal instanceof Array)) {
|
||||||
|
node.attributes[name] = [currVal];
|
||||||
|
}
|
||||||
|
node.attributes[name].push(value);
|
||||||
|
} else {
|
||||||
|
node.attributes[name] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Semicolon terminated line
|
||||||
|
node[count++] = line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param node
|
||||||
|
* A JSON node.
|
||||||
|
* @param depth
|
||||||
|
* The depth of the current node; used for indentation and
|
||||||
|
* optional.
|
||||||
|
* @param breaks
|
||||||
|
* Whether to add line breaks in the output.
|
||||||
|
*/
|
||||||
|
base.toCSS = function (node, depth, breaks) {
|
||||||
|
var cssString = '';
|
||||||
|
if (typeof depth == 'undefined') {
|
||||||
|
depth = 0;
|
||||||
|
}
|
||||||
|
if (typeof breaks == 'undefined') {
|
||||||
|
breaks = false;
|
||||||
|
}
|
||||||
|
if (node.attributes) {
|
||||||
|
for (i in node.attributes) {
|
||||||
|
var att = node.attributes[i];
|
||||||
|
if (att instanceof Array) {
|
||||||
|
for (var j = 0; j < att.length; j++) {
|
||||||
|
cssString += strAttr(i, att[j], depth);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cssString += strAttr(i, att, depth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (node.children) {
|
||||||
|
var first = true;
|
||||||
|
for (i in node.children) {
|
||||||
|
if (breaks && !first) {
|
||||||
|
cssString += '\n';
|
||||||
|
} else {
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
cssString += strNode(i, node.children[i], depth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cssString;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param data
|
||||||
|
* You can pass css string or the CSSJS.toJSON return value.
|
||||||
|
* @param id (Optional)
|
||||||
|
* To identify and easy removable of the style element
|
||||||
|
* @param replace (Optional. defaults to TRUE)
|
||||||
|
* Whether to remove or simply do nothing
|
||||||
|
* @return HTMLLinkElement
|
||||||
|
*/
|
||||||
|
base.toHEAD = function (data, id, replace) {
|
||||||
|
var head = document.getElementsByTagName('head')[0];
|
||||||
|
var xnode = document.getElementById(id);
|
||||||
|
var _xnodeTest = (xnode !== null && xnode instanceof HTMLStyleElement);
|
||||||
|
|
||||||
|
if (isEmpty(data) || !(head instanceof HTMLHeadElement)) return;
|
||||||
|
if (_xnodeTest) {
|
||||||
|
if (replace === true || isEmpty(replace)) {
|
||||||
|
xnode.removeAttribute('id');
|
||||||
|
} else return;
|
||||||
|
}
|
||||||
|
if (isCssJson(data)) {
|
||||||
|
data = base.toCSS(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
var node = document.createElement('style');
|
||||||
|
node.type = 'text/css';
|
||||||
|
|
||||||
|
if (!isEmpty(id)) {
|
||||||
|
node.id = id;
|
||||||
|
} else {
|
||||||
|
node.id = 'cssjson_' + timestamp();
|
||||||
|
}
|
||||||
|
if (node.styleSheet) {
|
||||||
|
node.styleSheet.cssText = data;
|
||||||
|
} else {
|
||||||
|
node.appendChild(document.createTextNode(data));
|
||||||
|
}
|
||||||
|
|
||||||
|
head.appendChild(node);
|
||||||
|
|
||||||
|
if (isValidStyleNode(node)) {
|
||||||
|
if (_xnodeTest) {
|
||||||
|
xnode.parentNode.removeChild(xnode);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
node.parentNode.removeChild(node);
|
||||||
|
if (_xnodeTest) {
|
||||||
|
xnode.setAttribute('id', id);
|
||||||
|
node = xnode;
|
||||||
|
} else return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Alias
|
||||||
|
|
||||||
|
if (typeof window != 'undefined') {
|
||||||
|
window.createCSS = base.toHEAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helpers
|
||||||
|
|
||||||
|
var isValidStyleNode = function (node) {
|
||||||
|
return (node instanceof HTMLStyleElement) && node.sheet.cssRules.length > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var timestamp = function () {
|
||||||
|
return Date.now() || +new Date();
|
||||||
|
};
|
||||||
|
|
||||||
|
var strAttr = function (name, value, depth) {
|
||||||
|
return '\t'.repeat(depth) + name + ': ' + value + ';\n';
|
||||||
|
};
|
||||||
|
|
||||||
|
var strNode = function (name, value, depth) {
|
||||||
|
var cssString = '\t'.repeat(depth) + name + ' {\n';
|
||||||
|
cssString += base.toCSS(value, depth + 1);
|
||||||
|
cssString += '\t'.repeat(depth) + '}\n';
|
||||||
|
return cssString;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
|
@ -12,6 +12,8 @@ var allowedTags = [
|
||||||
'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover', 'msgroup', 'mlongdiv', 'mscarries',
|
'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover', 'msgroup', 'mlongdiv', 'mscarries',
|
||||||
'mscarry', 'mstack'
|
'mscarry', 'mstack'
|
||||||
];
|
];
|
||||||
|
var cssClassesToTmpIds = {};
|
||||||
|
var tmpIdsToNewCss = {};
|
||||||
|
|
||||||
//////
|
//////
|
||||||
|
|
||||||
|
@ -188,9 +190,16 @@ function sanitize(rawContentString) {
|
||||||
});
|
});
|
||||||
lastFragment = tattrs.length === 0 ? '<a>' : '<a href="' + tattrs[0] + '">';
|
lastFragment = tattrs.length === 0 ? '<a>' : '<a href="' + tattrs[0] + '">';
|
||||||
} else {
|
} else {
|
||||||
lastFragment = '<' + tag + '>';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO ???
|
||||||
|
tattrs = attrs.filter(function(attr) {
|
||||||
|
return attr.name === 'data-class';
|
||||||
|
}).map(function(attr) {
|
||||||
|
return attr.value;
|
||||||
|
});
|
||||||
|
lastFragment = '<' + tag + ' class="' + tattrs[0] + '"' + '>';
|
||||||
|
|
||||||
results += lastFragment;
|
results += lastFragment;
|
||||||
lastFragment = '';
|
lastFragment = '';
|
||||||
},
|
},
|
||||||
|
@ -263,6 +272,74 @@ function getSelectedNodes() {
|
||||||
|
|
||||||
/////
|
/////
|
||||||
|
|
||||||
|
function jsonToCss(jsonObj) {
|
||||||
|
var keys = Object.keys(jsonObj);
|
||||||
|
var result = '';
|
||||||
|
for (var i = 0; i < keys.length; i++) {
|
||||||
|
var tmpJsonObj = jsonObj[keys[i]];
|
||||||
|
var tmpKeys = Object.keys(tmpJsonObj);
|
||||||
|
result += '.' + keys[i] + ' {';
|
||||||
|
for (var j = 0; j < tmpKeys.length; j++) {
|
||||||
|
result += tmpKeys[j] + ':' + tmpJsonObj[tmpKeys[j]] + ';';
|
||||||
|
}
|
||||||
|
result += '} ';
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function extractCss(callback) {
|
||||||
|
$('body').find('*').each(function (i, pre) {
|
||||||
|
if (!$(pre).is(':visible')) {
|
||||||
|
$(pre).replaceWith('');
|
||||||
|
} else {
|
||||||
|
var classNames = pre.getAttribute('class');
|
||||||
|
var tmpName = cssClassesToTmpIds[classNames];
|
||||||
|
var tmpNewCss = tmpIdsToNewCss[tmpName];
|
||||||
|
if (!tmpName) {
|
||||||
|
tmpName = 'class-' + Math.floor(Math.random()*100000);
|
||||||
|
cssClassesToTmpIds[classNames] = tmpName;
|
||||||
|
tmpIdsToNewCss[tmpName] = {};
|
||||||
|
}
|
||||||
|
if (!tmpNewCss) {
|
||||||
|
var style = window.getComputedStyle(pre);
|
||||||
|
tmpNewCss = {};
|
||||||
|
tmpNewCss['font-size'] = style['font-size'];
|
||||||
|
tmpNewCss['font-weight'] = style['font-weight'];
|
||||||
|
tmpNewCss['color'] = style['color'];
|
||||||
|
tmpNewCss['background-color'] = style['background-color'];
|
||||||
|
tmpIdsToNewCss[tmpName] = tmpNewCss;
|
||||||
|
}
|
||||||
|
pre.setAttribute('data-class', tmpName);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
getCurrentStyle(function (currentStyle) {
|
||||||
|
var styleText = currentStyle.style;
|
||||||
|
var json = CSSJSON.toJSON(styleText);
|
||||||
|
var keys = Object.keys(json.children);
|
||||||
|
for (var i = 0; i < keys.length; i++) {
|
||||||
|
if (json.children[keys[i]].children['display'] && json.children[keys[i]].children['display'] === 'none') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var cEls = document.querySelectorAll(keys[i]);
|
||||||
|
for (var j = 0; j < cEls.length; j++) {
|
||||||
|
var style = window.getComputedStyle(cEls[j]);
|
||||||
|
tmpNewCss = {};
|
||||||
|
tmpNewCss['font-size'] = style['font-size'];
|
||||||
|
tmpNewCss['font-weight'] = style['font-weight'];
|
||||||
|
tmpNewCss['color'] = style['color'];
|
||||||
|
tmpNewCss['background-color'] = style['background-color'];
|
||||||
|
tmpName = 'class-' + Math.floor(Math.random()*100000);
|
||||||
|
tmpIdsToNewCss[tmpName] = tmpNewCss;
|
||||||
|
var oldClass = cEls[j].getAttribute('data-class');
|
||||||
|
cEls[j].setAttribute('data-class', oldClass + ' ' + tmpName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
callback(jsonToCss(tmpIdsToNewCss));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/////
|
||||||
|
|
||||||
function deferredAddZip(url, filename) {
|
function deferredAddZip(url, filename) {
|
||||||
var deferred = $.Deferred();
|
var deferred = $.Deferred();
|
||||||
JSZipUtils.getBinaryContent(url, function(err, data) {
|
JSZipUtils.getBinaryContent(url, function(err, data) {
|
||||||
|
@ -286,43 +363,47 @@ chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
|
||||||
var result = {};
|
var result = {};
|
||||||
var pageSrc = '';
|
var pageSrc = '';
|
||||||
var tmpContent = '';
|
var tmpContent = '';
|
||||||
|
// var styleFile =
|
||||||
|
extractCss(function (styleFile) {
|
||||||
|
if (request.type === 'extract-page') {
|
||||||
|
pageSrc = document.getElementsByTagName('body')[0];
|
||||||
|
tmpContent = getContent(pageSrc);
|
||||||
|
} else if (request.type === 'extract-selection') {
|
||||||
|
pageSrc = getSelectedNodes();
|
||||||
|
pageSrc.forEach(function (page) {
|
||||||
|
tmpContent += getContent(page);
|
||||||
|
});
|
||||||
|
} else if (request.type === 'echo') {
|
||||||
|
sendResponse({
|
||||||
|
echo: true
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (request.type === 'extract-page') {
|
if (tmpContent.trim() === '') {
|
||||||
pageSrc = document.getElementsByTagName('body')[0];
|
sendResponse('');
|
||||||
tmpContent = getContent(pageSrc);
|
return;
|
||||||
} else if (request.type === 'extract-selection') {
|
}
|
||||||
pageSrc = getSelectedNodes();
|
|
||||||
pageSrc.forEach(function (page) {
|
allImages.forEach(function (tmpImg) {
|
||||||
tmpContent += getContent(page);
|
imgsPromises.push(deferredAddZip(tmpImg.originalUrl, tmpImg.filename));
|
||||||
});
|
});
|
||||||
} else if (request.type === 'echo') {
|
|
||||||
sendResponse({
|
$.when.apply($, imgsPromises).done(function() {
|
||||||
echo: true
|
var tmpTitle = getPageTitle(document.title);
|
||||||
|
result = {
|
||||||
|
url: getPageUrl(tmpTitle),
|
||||||
|
title: tmpTitle,
|
||||||
|
baseUrl: getCurrentUrl(),
|
||||||
|
styleFileContent: styleFile,
|
||||||
|
styleFileName: 'style'+Math.floor(Math.random()*100000)+'.css',
|
||||||
|
images: extractedImages,
|
||||||
|
content: tmpContent
|
||||||
|
};
|
||||||
|
sendResponse(result);
|
||||||
|
}).fail(function(e) {
|
||||||
|
console.log('Error:', e);
|
||||||
});
|
});
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tmpContent.trim() === '') {
|
|
||||||
sendResponse('');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
allImages.forEach(function (tmpImg) {
|
|
||||||
imgsPromises.push(deferredAddZip(tmpImg.originalUrl, tmpImg.filename));
|
|
||||||
});
|
|
||||||
|
|
||||||
$.when.apply($, imgsPromises).done(function() {
|
|
||||||
var tmpTitle = getPageTitle(document.title);
|
|
||||||
result = {
|
|
||||||
url: getPageUrl(tmpTitle),
|
|
||||||
title: tmpTitle,
|
|
||||||
baseUrl: getCurrentUrl(),
|
|
||||||
images: extractedImages,
|
|
||||||
content: tmpContent
|
|
||||||
};
|
|
||||||
sendResponse(result);
|
|
||||||
}).fail(function(e) {
|
|
||||||
console.log('Error:', e);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
},
|
},
|
||||||
"content_scripts": [{
|
"content_scripts": [{
|
||||||
"matches": ["<all_urls>"],
|
"matches": ["<all_urls>"],
|
||||||
"js": ["jquery.js", "jszip.js", "jszip-utils.js", "utils.js", "pure-parser.js", "extractHtml.js"]
|
"js": ["jquery.js", "jszip.js", "jszip-utils.js", "utils.js", "pure-parser.js", "cssjson.js", "extractHtml.js"]
|
||||||
}],
|
}],
|
||||||
"background": {
|
"background": {
|
||||||
"scripts": ["background.js"]
|
"scripts": ["background.js"]
|
||||||
|
|
|
@ -74,6 +74,17 @@
|
||||||
<body>
|
<body>
|
||||||
<div class="menu-holder">
|
<div class="menu-holder">
|
||||||
<div id="menuTitle">Save as eBook:</div>
|
<div id="menuTitle">Save as eBook:</div>
|
||||||
|
<hr/>
|
||||||
|
<div><label for="">Custom Styles:</label></div>
|
||||||
|
<div>
|
||||||
|
<select id="allStylesList" class="" name="" style="display:inline-block;width:100%;">
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="">
|
||||||
|
<button id="applyStyle" type="button" name="button" style="display:inline-block;width:47%;border-right:solid 1px black;">Apply</button>
|
||||||
|
<button id="editStyles" type="button" name="button" style="display:inline-block;width:47%;">Edit Styles ...</button>
|
||||||
|
</div>
|
||||||
|
<hr/>
|
||||||
<button id="savePage" type="button" name="button">Save Page</button>
|
<button id="savePage" type="button" name="button">Save Page</button>
|
||||||
<button id="saveSelection" type="button" name="button">Save Selection</button>
|
<button id="saveSelection" type="button" name="button">Save Selection</button>
|
||||||
<hr/>
|
<hr/>
|
||||||
|
|
|
@ -1,3 +1,93 @@
|
||||||
|
var allStyles = [];
|
||||||
|
var currentStyle = null;
|
||||||
|
|
||||||
|
getStyles(createStyleList);
|
||||||
|
|
||||||
|
function createStyleList(styles) {
|
||||||
|
allStyles = styles;
|
||||||
|
chrome.tabs.query({'active': true}, function (tabs) {
|
||||||
|
var currentUrl = tabs[0].url;
|
||||||
|
|
||||||
|
if (!styles || styles.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var existingStyles = document.getElementById('allStylesList');
|
||||||
|
var foundMatchingUrl = false;
|
||||||
|
|
||||||
|
while (existingStyles.hasChildNodes() && existingStyles.childElementCount > 1) {
|
||||||
|
existingStyles.removeChild(existingStyles.lastChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < styles.length; i++) {
|
||||||
|
var listItem = document.createElement('option');
|
||||||
|
listItem.id = 'option_' + i;
|
||||||
|
listItem.className = 'cssEditor-chapter-item';
|
||||||
|
listItem.value = 'option_' + i;
|
||||||
|
listItem.innerText = styles[i].title;
|
||||||
|
|
||||||
|
if (!foundMatchingUrl) {
|
||||||
|
currentUrl = currentUrl.replace(/(http[s]?:\/\/|www\.)/gi, '').toLowerCase();
|
||||||
|
var styleUrl = styles[i].url.replace(/(http[s]?:\/\/|www\.)/gi, '').toLowerCase();
|
||||||
|
|
||||||
|
if (currentUrl.startsWith(styleUrl)) {
|
||||||
|
listItem.selected = 'selected';
|
||||||
|
foundMatchingUrl = true;
|
||||||
|
currentStyle = styles[i];
|
||||||
|
setCurrentStyle(currentStyle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
existingStyles.appendChild(listItem);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('allStylesList').onchange = function () {
|
||||||
|
var newValue = this.value;
|
||||||
|
newValue = newValue.replace('option_', '');
|
||||||
|
newValue = parseInt(newValue);
|
||||||
|
currentStyle = allStyles[newValue];
|
||||||
|
setCurrentStyle(currentStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById("applyStyle").onclick = function() {
|
||||||
|
chrome.tabs.query({
|
||||||
|
currentWindow: true,
|
||||||
|
active: true
|
||||||
|
}, function(tab) {
|
||||||
|
chrome.tabs.insertCSS(tab[0].id, {code: currentStyle.style});
|
||||||
|
// window.close(); TODO ?
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById("editStyles").onclick = function() {
|
||||||
|
|
||||||
|
if (document.getElementById('cssEditor-Modal')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
chrome.tabs.query({
|
||||||
|
currentWindow: true,
|
||||||
|
active: true
|
||||||
|
}, function(tab) {
|
||||||
|
|
||||||
|
chrome.tabs.executeScript(tab[0].id, {file: '/jquery.js'});
|
||||||
|
chrome.tabs.executeScript(tab[0].id, {file: '/utils.js'});
|
||||||
|
chrome.tabs.executeScript(tab[0].id, {file: '/filesaver.js'});
|
||||||
|
chrome.tabs.executeScript(tab[0].id, {file: '/jszip.js'});
|
||||||
|
chrome.tabs.executeScript(tab[0].id, {file: '/jszip-utils.js'});
|
||||||
|
chrome.tabs.executeScript(tab[0].id, {file: '/saveEbook.js'});
|
||||||
|
chrome.tabs.executeScript(tab[0].id, {file: '/jquery-sortable.js'});
|
||||||
|
chrome.tabs.insertCSS(tab[0].id, {file: '/cssEditor.css'});
|
||||||
|
|
||||||
|
chrome.tabs.executeScript(tab[0].id, {
|
||||||
|
file: '/cssEditor.js'
|
||||||
|
});
|
||||||
|
|
||||||
|
window.close();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
document.getElementById("editChapters").onclick = function() {
|
document.getElementById("editChapters").onclick = function() {
|
||||||
|
|
||||||
|
@ -46,6 +136,7 @@ function dispatch(action, justAddToBuffer) {
|
||||||
chrome.tabs.executeScript(tab[0].id, {file: '/jszip.js'});
|
chrome.tabs.executeScript(tab[0].id, {file: '/jszip.js'});
|
||||||
chrome.tabs.executeScript(tab[0].id, {file: '/jszip-utils.js'});
|
chrome.tabs.executeScript(tab[0].id, {file: '/jszip-utils.js'});
|
||||||
chrome.tabs.executeScript(tab[0].id, {file: '/pure-parser.js'});
|
chrome.tabs.executeScript(tab[0].id, {file: '/pure-parser.js'});
|
||||||
|
chrome.tabs.executeScript(tab[0].id, {file: '/cssjson.js'});
|
||||||
|
|
||||||
chrome.tabs.executeScript(tab[0].id, {
|
chrome.tabs.executeScript(tab[0].id, {
|
||||||
file: 'extractHtml.js'
|
file: 'extractHtml.js'
|
||||||
|
|
|
@ -98,7 +98,11 @@ function _buildEbook(allPages) {
|
||||||
'</ncx>'
|
'</ncx>'
|
||||||
);
|
);
|
||||||
|
|
||||||
oebps.file(cssFileName, '');
|
oebps.file(cssFileName, ''); //TODO
|
||||||
|
var styleFolder = oebps.folder('style');
|
||||||
|
allPages.forEach(function(page) {
|
||||||
|
styleFolder.file(page.styleFileName, page.styleFileContent);
|
||||||
|
});
|
||||||
|
|
||||||
var pagesFolder = oebps.folder('pages');
|
var pagesFolder = oebps.folder('pages');
|
||||||
allPages.forEach(function(page) {
|
allPages.forEach(function(page) {
|
||||||
|
@ -107,7 +111,7 @@ function _buildEbook(allPages) {
|
||||||
'<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops">' +
|
'<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops">' +
|
||||||
'<head>' +
|
'<head>' +
|
||||||
'<title>' + page.title + '</title>' +
|
'<title>' + page.title + '</title>' +
|
||||||
'<link href="../' + cssFileName + '" rel="stylesheet" type="text/css" />' +
|
'<link href="../style/' + page.styleFileName + '" rel="stylesheet" type="text/css" />' +
|
||||||
'</head><body>' +
|
'</head><body>' +
|
||||||
page.content +
|
page.content +
|
||||||
'</body></html>'
|
'</body></html>'
|
||||||
|
|
|
@ -1,3 +1,36 @@
|
||||||
|
|
||||||
|
function setCurrentStyle(currentStyle) {
|
||||||
|
chrome.runtime.sendMessage({
|
||||||
|
type: "set current style",
|
||||||
|
currentStyle: currentStyle
|
||||||
|
}, function(response) {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCurrentStyle(callback) {
|
||||||
|
chrome.runtime.sendMessage({
|
||||||
|
type: "get current style"
|
||||||
|
}, function(response) {
|
||||||
|
callback(response.currentStyle);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getStyles(callback) {
|
||||||
|
chrome.runtime.sendMessage({
|
||||||
|
type: "get styles"
|
||||||
|
}, function(response) {
|
||||||
|
callback(response.styles);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function setStyles(styles) {
|
||||||
|
chrome.runtime.sendMessage({
|
||||||
|
type: "set styles",
|
||||||
|
styles: styles
|
||||||
|
}, function(response) {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function getEbookTitle(callback) {
|
function getEbookTitle(callback) {
|
||||||
chrome.runtime.sendMessage({
|
chrome.runtime.sendMessage({
|
||||||
type: "get title"
|
type: "get title"
|
||||||
|
@ -119,6 +152,7 @@ function getAbsoluteUrl(urlStr) {
|
||||||
} else if (urlStr.indexOf('http') !== 0) {
|
} else if (urlStr.indexOf('http') !== 0) {
|
||||||
absoluteUrl = currentUrl + '/' + urlStr;
|
absoluteUrl = currentUrl + '/' + urlStr;
|
||||||
}
|
}
|
||||||
|
absoluteUrl = absoluteUrl.replace(/&/ig, '&'); //TODO ?
|
||||||
return absoluteUrl;
|
return absoluteUrl;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log('Error:', e);
|
console.log('Error:', e);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue