add: resize image
This commit is contained in:
parent
781cea3361
commit
ef7071266a
30
build.js
30
build.js
|
|
@ -112,6 +112,36 @@ async function main() {
|
|||
} s.`
|
||||
);
|
||||
|
||||
await esbuild
|
||||
.build({
|
||||
entryPoints: ["src/editor/editorScript.ts"],
|
||||
bundle: true,
|
||||
outfile: path.join(buildDir, "temp/editorScript.js"),
|
||||
// minify: true,
|
||||
target: ["firefox60"],
|
||||
})
|
||||
.catch(() => process.exit(1));
|
||||
|
||||
const optionsScript = {
|
||||
files: [path.join(buildDir, "addon/chrome/content/scripts/index.js")],
|
||||
from: [/__placeholder:editorScript.js__/g],
|
||||
to: [
|
||||
fs
|
||||
.readFileSync(path.join(buildDir, "temp/editorScript.js"))
|
||||
.toString()
|
||||
.replace(/\\/g, "\\\\"),
|
||||
],
|
||||
countMatches: true,
|
||||
};
|
||||
|
||||
_ = replace.sync(optionsScript);
|
||||
console.log(
|
||||
"[Build] Run replace in ",
|
||||
_.filter((f) => f.hasChanged).map(
|
||||
(f) => `${f.file} : ${f.numReplacements} / ${f.numMatches}`
|
||||
)
|
||||
);
|
||||
|
||||
const optionsAddon = {
|
||||
files: [
|
||||
path.join(buildDir, "**/*.rdf"),
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
"compressing": "^1.5.1",
|
||||
"crypto-js": "^4.1.1",
|
||||
"esbuild": "^0.14.34",
|
||||
"prosemirror-transform": "^1.7.0",
|
||||
"replace-in-file": "^6.3.2",
|
||||
"seedrandom": "^3.0.5",
|
||||
"tree-model": "^1.0.7",
|
||||
|
|
|
|||
|
|
@ -26,6 +26,15 @@ class EditorController extends AddonBase {
|
|||
await this.editorPromise.promise;
|
||||
}
|
||||
|
||||
injectScripts(_window: Window) {
|
||||
if (!_window.document.getElementById("betternotes-script")) {
|
||||
const messageScript = _window.document.createElement("script");
|
||||
messageScript.id = "betternotes-script";
|
||||
messageScript.innerHTML = `__placeholder:editorScript.js__`;
|
||||
_window.document.head.append(messageScript);
|
||||
}
|
||||
}
|
||||
|
||||
recordEditor(instance: Zotero.EditorInstance) {
|
||||
this.editorHistory.push({
|
||||
instance: instance,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,135 @@
|
|||
// TODO: Move this somewhere else
|
||||
const { Fragment, Slice } = require("prosemirror-model");
|
||||
const { Step, StepResult } = require("prosemirror-transform");
|
||||
|
||||
class SetAttrsStep extends Step {
|
||||
// :: (number, Object | null)
|
||||
constructor(pos, attrs) {
|
||||
super();
|
||||
this.pos = pos;
|
||||
this.attrs = attrs;
|
||||
}
|
||||
|
||||
apply(doc) {
|
||||
let target = doc.nodeAt(this.pos);
|
||||
if (!target) return StepResult.fail("No node at given position");
|
||||
let newNode = target.type.create(this.attrs, Fragment.emtpy, target.marks);
|
||||
let slice = new Slice(Fragment.from(newNode), 0, target.isLeaf ? 0 : 1);
|
||||
return StepResult.fromReplace(doc, this.pos, this.pos + 1, slice);
|
||||
}
|
||||
|
||||
invert(doc) {
|
||||
let target = doc.nodeAt(this.pos);
|
||||
return new SetAttrsStep(this.pos, target ? target.attrs : null);
|
||||
}
|
||||
|
||||
map(mapping) {
|
||||
let pos = mapping.mapResult(this.pos, 1);
|
||||
return pos.deleted ? null : new SetAttrsStep(pos.pos, this.attrs);
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return { stepType: "setAttrs", pos: this.pos, attrs: this.attrs };
|
||||
}
|
||||
|
||||
static fromJSON(schema, json) {
|
||||
if (
|
||||
typeof json.pos != "number" ||
|
||||
(json.attrs != null && typeof json.attrs != "object")
|
||||
)
|
||||
throw new RangeError("Invalid input for SetAttrsStep.fromJSON");
|
||||
return new SetAttrsStep(json.pos, json.attrs);
|
||||
}
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
window.SetAttrsStep = SetAttrsStep;
|
||||
|
||||
// @ts-ignore
|
||||
window.updateImageDimensions = function (
|
||||
nodeID,
|
||||
width,
|
||||
height,
|
||||
state,
|
||||
dispatch
|
||||
) {
|
||||
let { tr } = state;
|
||||
console.log(nodeID, width, height, state, dispatch);
|
||||
state.doc.descendants((node, pos) => {
|
||||
if (node.type.name === "image" && node.attrs.nodeID === nodeID) {
|
||||
tr.step(new SetAttrsStep(pos, { ...node.attrs, width, height }));
|
||||
tr.setMeta("addToHistory", false);
|
||||
tr.setMeta("system", true);
|
||||
dispatch(tr);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
window.addEventListener(
|
||||
"message",
|
||||
async (e) => {
|
||||
if (e.data.type === "exportPDF") {
|
||||
console.log("exportPDF");
|
||||
const container = document.getElementById(
|
||||
"editor-container"
|
||||
) as HTMLElement;
|
||||
container.style.display = "none";
|
||||
|
||||
const fullPageStyle = document.createElement("style");
|
||||
fullPageStyle.innerHTML =
|
||||
"@page { margin: 0; } @media print{ body { height : auto; -webkit-print-color-adjust: exact; color-adjust: exact; }}";
|
||||
document.body.append(fullPageStyle);
|
||||
|
||||
let t = 0;
|
||||
let imageFlag = false;
|
||||
while (!imageFlag && t < 500) {
|
||||
await new Promise(function (resolve) {
|
||||
setTimeout(resolve, 10);
|
||||
});
|
||||
imageFlag = !Array.prototype.find.call(
|
||||
document.querySelectorAll("img"),
|
||||
(e) => !e.getAttribute("src") || e.style.display === "none"
|
||||
);
|
||||
t += 1;
|
||||
}
|
||||
|
||||
const editNode = document.querySelector(".primary-editor") as HTMLElement;
|
||||
const printNode = editNode.cloneNode(true) as HTMLElement;
|
||||
printNode.style.padding = "20px";
|
||||
document.body.append(printNode);
|
||||
|
||||
let printFlag = false;
|
||||
window.onafterprint = (e) => {
|
||||
console.log("Print Dialog Closed..");
|
||||
printFlag = true;
|
||||
document.title = "Printed";
|
||||
};
|
||||
window.onmouseover = (e) => {
|
||||
if (printFlag) {
|
||||
document.title = "Printed";
|
||||
printNode.remove();
|
||||
container.style.removeProperty("display");
|
||||
}
|
||||
};
|
||||
document.title = (printNode?.firstChild as HTMLElement).innerText;
|
||||
console.log(document.title);
|
||||
window.print();
|
||||
} else if (e.data.type === "resizeImage") {
|
||||
console.log("resizeImage");
|
||||
// @ts-ignore
|
||||
window.updateImageDimensions(
|
||||
// @ts-ignore
|
||||
_currentEditorInstance._editorCore.view.state.selection.node.attrs
|
||||
.nodeID,
|
||||
e.data.width,
|
||||
undefined,
|
||||
// @ts-ignore
|
||||
_currentEditorInstance._editorCore.view.state,
|
||||
// @ts-ignore
|
||||
_currentEditorInstance._editorCore.view.dispatch
|
||||
);
|
||||
}
|
||||
},
|
||||
false
|
||||
);
|
||||
|
|
@ -324,57 +324,7 @@ class EditorViews extends AddonBase {
|
|||
_window.document.body.append(style);
|
||||
}
|
||||
|
||||
if (!_window.document.getElementById("betternotes-script")) {
|
||||
const messageScript = _window.document.createElement("script");
|
||||
messageScript.id = "betternotes-script";
|
||||
messageScript.innerHTML = `
|
||||
window.addEventListener('message', async (e)=>{
|
||||
if(e.data.type === "exportPDF"){
|
||||
console.log("exportPDF");
|
||||
const container = document.getElementById("editor-container");
|
||||
container.style.display = "none";
|
||||
|
||||
const fullPageStyle = document.createElement("style");
|
||||
fullPageStyle.innerHTML =
|
||||
"@page { margin: 0; } @media print{ body { height : auto; -webkit-print-color-adjust: exact; color-adjust: exact; }}";
|
||||
document.body.append(fullPageStyle);
|
||||
|
||||
let t = 0;
|
||||
let imageFlag = false;
|
||||
while(!imageFlag && t < 500){
|
||||
await new Promise(function (resolve) {
|
||||
setTimeout(resolve, 10);
|
||||
});
|
||||
imageFlag = !Array.prototype.find.call(document.querySelectorAll('img'), e=>(!e.getAttribute('src') || e.style.display === 'none'));
|
||||
t += 1;
|
||||
}
|
||||
|
||||
const editNode = document.querySelector(".primary-editor");
|
||||
const printNode = editNode.cloneNode(true);
|
||||
printNode.style.padding = "20px";
|
||||
document.body.append(printNode);
|
||||
|
||||
let printFlag = false;
|
||||
window.onafterprint = (e) => {
|
||||
console.log('Print Dialog Closed..');
|
||||
printFlag = true;
|
||||
document.title = "Printed";
|
||||
};
|
||||
window.onmouseover = (e) => {
|
||||
if (printFlag) {
|
||||
document.title = "Printed";
|
||||
printNode.remove();
|
||||
container.style.removeProperty('display');
|
||||
}
|
||||
};
|
||||
document.title = printNode.firstChild.innerText;
|
||||
console.log(document.title);
|
||||
window.print();
|
||||
}
|
||||
}, false)
|
||||
`;
|
||||
_window.document.head.append(messageScript);
|
||||
}
|
||||
this._Addon.EditorController.injectScripts(_window);
|
||||
|
||||
const moreDropdown: HTMLElement = Array.prototype.filter.call(
|
||||
_window.document.querySelectorAll(".more-dropdown"),
|
||||
|
|
@ -898,6 +848,13 @@ class EditorViews extends AddonBase {
|
|||
return res;
|
||||
};
|
||||
|
||||
const checkImageSelected = () => {
|
||||
return (
|
||||
(instance._iframeWindow as any).wrappedJSObject._currentEditorInstance
|
||||
._editorCore.view.state.selection.node?.type?.name === "image"
|
||||
);
|
||||
};
|
||||
|
||||
const elementOptions: XULElementOptions = {
|
||||
tag: "fragment",
|
||||
subElementOptions: [
|
||||
|
|
@ -907,6 +864,43 @@ class EditorViews extends AddonBase {
|
|||
checkExistanceParent: instance._popup,
|
||||
ignoreIfExists: true,
|
||||
},
|
||||
{
|
||||
tag: "menuitem",
|
||||
id: "menupopup-resizeImage",
|
||||
checkExistanceParent: instance._popup,
|
||||
ignoreIfExists: true,
|
||||
attributes: [["label", "Resize Image"]],
|
||||
customCheck: checkImageSelected,
|
||||
listeners: [
|
||||
[
|
||||
"command",
|
||||
(e) => {
|
||||
const newWidth = parseFloat(
|
||||
prompt(
|
||||
"Enter new width (px):",
|
||||
(instance._iframeWindow as any).wrappedJSObject
|
||||
._currentEditorInstance._editorCore.view.state.selection
|
||||
.node?.attrs?.width
|
||||
)
|
||||
);
|
||||
if (newWidth && newWidth > 10) {
|
||||
instance._iframeWindow.postMessage(
|
||||
{ type: "resizeImage", width: newWidth },
|
||||
"*"
|
||||
);
|
||||
}
|
||||
},
|
||||
undefined,
|
||||
],
|
||||
],
|
||||
},
|
||||
{
|
||||
tag: "menuseparator",
|
||||
id: "menupopup-resizeimagesplitter",
|
||||
checkExistanceParent: instance._popup,
|
||||
customCheck: checkImageSelected,
|
||||
ignoreIfExists: true,
|
||||
},
|
||||
{
|
||||
tag: "menuitem",
|
||||
id: "menupopup-copylink",
|
||||
|
|
|
|||
|
|
@ -386,6 +386,9 @@ class ZoteroViews extends AddonBase {
|
|||
doc.querySelector(`#${options.id}`).remove();
|
||||
}
|
||||
}
|
||||
if (options.customCheck && !options.customCheck()) {
|
||||
return undefined;
|
||||
}
|
||||
const element = createElement();
|
||||
if (options.id) {
|
||||
element.id = options.id;
|
||||
|
|
|
|||
|
|
@ -19,5 +19,6 @@ declare interface XULElementOptions {
|
|||
checkExistanceParent?: HTMLElement;
|
||||
ignoreIfExists?: boolean;
|
||||
removeIfExists?: boolean;
|
||||
customCheck?: () => boolean;
|
||||
subElementOptions?: Array<XULElementOptions>;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue