mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-27 10:32:58 +02:00
238 lines
7.0 KiB
JavaScript
238 lines
7.0 KiB
JavaScript
(function() {
|
|
|
|
if (window.jopext_hasRun) return;
|
|
window.jopext_hasRun = true;
|
|
|
|
console.info('jopext: Loading content script');
|
|
|
|
let browser_ = null;
|
|
if (typeof browser !== 'undefined') {
|
|
browser_ = browser;
|
|
browserSupportsPromises_ = true;
|
|
} else if (typeof chrome !== 'undefined') {
|
|
browser_ = chrome;
|
|
browserSupportsPromises_ = false;
|
|
}
|
|
|
|
function pageTitle() {
|
|
const titleElements = document.getElementsByTagName("title");
|
|
if (titleElements.length) return titleElements[0].text.trim();
|
|
return document.title.trim();
|
|
}
|
|
|
|
function baseUrl() {
|
|
let output = location.origin + location.pathname;
|
|
if (output[output.length - 1] !== '/') {
|
|
output = output.split('/');
|
|
output.pop();
|
|
output = output.join('/');
|
|
}
|
|
return output;
|
|
}
|
|
|
|
// Cleans up element by removing all its invisible children (which we don't want to render as Markdown)
|
|
function cleanUpElement(element) {
|
|
const childNodes = element.childNodes;
|
|
|
|
for (let i = 0; i < childNodes.length; i++) {
|
|
const node = childNodes[i];
|
|
|
|
let isVisible = node.nodeType === 1 ? window.getComputedStyle(node).display !== 'none' : true;
|
|
if (isVisible && ['input', 'textarea', 'script', 'style', 'select', 'option', 'button'].indexOf(node.nodeName.toLowerCase()) >= 0) isVisible = false;
|
|
|
|
if (!isVisible) {
|
|
element.removeChild(node);
|
|
} else {
|
|
cleanUpElement(node);
|
|
}
|
|
}
|
|
}
|
|
|
|
function readabilityProcess() {
|
|
var uri = {
|
|
spec: location.href,
|
|
host: location.host,
|
|
prePath: location.protocol + "//" + location.host,
|
|
scheme: location.protocol.substr(0, location.protocol.indexOf(":")),
|
|
pathBase: location.protocol + "//" + location.host + location.pathname.substr(0, location.pathname.lastIndexOf("/") + 1)
|
|
};
|
|
|
|
// Readability directly change the passed document so clone it so as
|
|
// to preserve the original web page.
|
|
const documentClone = document.cloneNode(true);
|
|
const readability = new Readability(documentClone); // new window.Readability(uri, documentClone);
|
|
const article = readability.parse();
|
|
|
|
if (!article) throw new Error('Could not parse HTML document with Readability');
|
|
|
|
return {
|
|
title: article.title,
|
|
body: article.content,
|
|
}
|
|
}
|
|
|
|
async function prepareCommandResponse(command) {
|
|
console.info('Got command: ' + command.name);
|
|
|
|
if (command.name === "simplifiedPageHtml") {
|
|
|
|
let article = null;
|
|
try {
|
|
article = readabilityProcess();
|
|
} catch (error) {
|
|
console.warn(error);
|
|
console.warn('Sending full page HTML instead');
|
|
const newCommand = Object.assign({}, command, { name: 'completePageHtml' });
|
|
const response = await prepareCommandResponse(newCommand);
|
|
response.warning = 'Could not retrieve simplified version of page - full page has been saved instead.';
|
|
return response;
|
|
}
|
|
|
|
return {
|
|
name: 'clippedContent',
|
|
html: article.body,
|
|
title: article.title,
|
|
baseUrl: baseUrl(),
|
|
url: location.origin + location.pathname,
|
|
};
|
|
|
|
} else if (command.name === "completePageHtml") {
|
|
|
|
const cleanDocument = document.body.cloneNode(true);
|
|
cleanUpElement(cleanDocument);
|
|
|
|
return {
|
|
name: 'clippedContent',
|
|
html: cleanDocument.innerHTML,
|
|
title: pageTitle(),
|
|
baseUrl: baseUrl(),
|
|
url: location.origin + location.pathname,
|
|
};
|
|
|
|
} else if (command.name === 'screenshot') {
|
|
|
|
const overlay = document.createElement('div');
|
|
overlay.style.opacity = '0.4';
|
|
overlay.style.background = 'black';
|
|
overlay.style.width = '100%';
|
|
overlay.style.height = '100%';
|
|
overlay.style.zIndex = 99999999;
|
|
overlay.style.top = 0;
|
|
overlay.style.left = 0;
|
|
overlay.style.position = 'fixed';
|
|
|
|
document.body.appendChild(overlay);
|
|
|
|
const messageComp = document.createElement('div');
|
|
|
|
const messageCompWidth = 300;
|
|
messageComp.style.position = 'fixed'
|
|
messageComp.style.opacity = '0.9'
|
|
messageComp.style.width = messageCompWidth + 'px'
|
|
messageComp.style.maxWidth = messageCompWidth + 'px'
|
|
messageComp.style.border = '1px solid black'
|
|
messageComp.style.background = 'white'
|
|
messageComp.style.top = '10px'
|
|
messageComp.style.textAlign = 'center';
|
|
messageComp.style.padding = '6px'
|
|
messageComp.style.left = Math.round(document.body.clientWidth / 2 - messageCompWidth / 2) + 'px'
|
|
messageComp.style.zIndex = overlay.style.zIndex + 1
|
|
|
|
messageComp.textContent = 'Drag and release to capture a screenshot';
|
|
|
|
document.body.appendChild(messageComp);
|
|
|
|
const selection = document.createElement('div');
|
|
selection.style.opacity = '0.4';
|
|
selection.style.border = '1px solid red';
|
|
selection.style.background = 'white';
|
|
selection.style.border = '2px solid black';
|
|
selection.style.zIndex = overlay.style.zIndex - 1;
|
|
selection.style.top = 0;
|
|
selection.style.left = 0;
|
|
selection.style.position = 'fixed';
|
|
|
|
document.body.appendChild(selection);
|
|
|
|
let isDragging = false;
|
|
let draggingStartPos = null;
|
|
let selectionArea = {};
|
|
|
|
function updateSelection() {
|
|
selection.style.left = selectionArea.x + 'px';
|
|
selection.style.top = selectionArea.y + 'px';
|
|
selection.style.width = selectionArea.width + 'px';
|
|
selection.style.height = selectionArea.height + 'px';
|
|
}
|
|
|
|
function setSelectionSizeFromMouse(event) {
|
|
selectionArea.width = Math.max(1, event.clientX - draggingStartPos.x);
|
|
selectionArea.height = Math.max(1, event.clientY - draggingStartPos.y);
|
|
updateSelection();
|
|
}
|
|
|
|
function selection_mouseDown(event) {
|
|
selectionArea = { x: event.clientX, y: event.clientY, width: 0, height: 0 }
|
|
draggingStartPos = { x: event.clientX, y: event.clientY };
|
|
isDragging = true;
|
|
updateSelection();
|
|
}
|
|
|
|
function selection_mouseMove(event) {
|
|
if (!isDragging) return;
|
|
setSelectionSizeFromMouse(event);
|
|
}
|
|
|
|
function selection_mouseUp(event) {
|
|
setSelectionSizeFromMouse(event);
|
|
|
|
isDragging = false;
|
|
|
|
overlay.removeEventListener('mousedown', selection_mouseDown);
|
|
overlay.removeEventListener('mousemove', selection_mouseMove);
|
|
overlay.removeEventListener('mouseup', selection_mouseUp);
|
|
|
|
document.body.removeChild(overlay);
|
|
document.body.removeChild(selection);
|
|
document.body.removeChild(messageComp);
|
|
|
|
if (!selectionArea || !selectionArea.width || !selectionArea.height) return;
|
|
|
|
setTimeout(() => {
|
|
const content = {
|
|
title: pageTitle(),
|
|
cropRect: selectionArea,
|
|
url: location.origin + location.pathname,
|
|
};
|
|
|
|
browser_.runtime.sendMessage({
|
|
name: 'screenshotArea',
|
|
content: content,
|
|
apiBaseUrl: command.apiBaseUrl,
|
|
});
|
|
}, 10);
|
|
}
|
|
|
|
overlay.addEventListener('mousedown', selection_mouseDown);
|
|
overlay.addEventListener('mousemove', selection_mouseMove);
|
|
overlay.addEventListener('mouseup', selection_mouseUp);
|
|
|
|
return {};
|
|
|
|
} else {
|
|
throw new Error('Unknown command: ' + JSON.stringify(command));
|
|
}
|
|
}
|
|
|
|
async function execCommand(command) {
|
|
const response = await prepareCommandResponse(command);
|
|
browser_.runtime.sendMessage(response);
|
|
}
|
|
|
|
browser_.runtime.onMessage.addListener((command) => {
|
|
console.info('jopext: Got command:', command);
|
|
|
|
execCommand(command);
|
|
});
|
|
|
|
})(); |